Are Context and MainActivity.this different? - android

In MainActivity, Context and MainActivity are different?
They are exactly getApplicationContext() and MainActivity.this in Method.
The reason I'm asking this is because i got error because of them.
if these are different, Complier didn't display red line in code.
I thought it was the same until now.
I got this error code.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.writeweight, PID: 24595
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:843)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:806)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:693)
at androidx.appcompat.app.AppCompatDialog.setContentView(AppCompatDialog.java:95)
at androidx.appcompat.app.AlertController.installContent(AlertController.java:232)
at androidx.appcompat.app.AlertDialog.onCreate(AlertDialog.java:279)
at android.app.Dialog.dispatchOnCreate(Dialog.java:702)
at android.app.Dialog.show(Dialog.java:424)
at com.example.writeweight.MainActivity.onOptionsItemSelected(MainActivity.java:85)
at android.app.Activity.onMenuItemSelected(Activity.java:4182)
And I changed from getApplicationContext() to MainActivity.this and it worked well.
Code
MainActivity.class
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); // HERE
builder.setTitle("SET");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(),"TEST", Toast.LENGTH_SHORT).show();
}
});
AlertDialog dialog = builder.create();
dialog.show();
return true;
}
Tell me please.
Thank you

getApplicationContext() (somewhat unsurprisingly) returns the application context, whilst MainActivity.this is itself an activity context. Themes associated with your activity will differ from your application. They aren't the same thing.
if these are different, Complier didn't display red line in code.
You wont see an error, because it's only a Context that is requested. I haven't tried it, but you probably could use an Application instance so long as you specify the theme as well by using new AlertDialog.Builder(getApplicationContext(), /* theme res id */)
However, all the examples in the Android documentation use an Activity context, so I'd suggest you just go with that.

Related

I need to display a simple AlertDialog within a called class

I'm very new to Android, and have a basic question. I need at certain points to display a user notification in a dialog box, which they can simply acknowledge with the OK button.
I'm using:
myActivity.runOnUiThread(new Runnable() {
public void run() {
AlertDialog alertDialog = new AlertDialog.Builder(myContext).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("My message");
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
});
This works well in the Main program, but within a called method it needs the Activity and the Context from the main program. Can anybody tell me how to pass these? getApplicationContext() seems to be acceptable, but I can't figure out how to pass the Activity.
Better still of course would be to get the parent Context and Activity within the method, but I can't get that to work either.
I'd be grateful for any help.
-update 10/07/21
Rahul has given me the solution to the problem I posed: how to pass in the Activity and Context.
The problem is that the dialog still doesn't show.
I found a variation online as follows:
AlertDialog.Builder builder = new AlertDialog.Builder(myContext);
builder.setTitle("Alert")
.setMessage("My message")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
but this doesn't work either.
I'm puzzled that such a common and simple task needs so much code. In the desktop languages I'm used to it can be done in a single line.
So my titled question stands, but can anyone see where the code is faulty?
Many thanks
You can either pass activity to the class when initializing the object or you can pass activity when calling the function.
Case 1 (Recommended)
Pass Activity when calling the function:
MyObj myObj = new MyObj();
myObj.showDialog(myValue, ActivityName.this);
Where function will look like this:
public void showDialog(int myValue, Activity activity){
...
}
Then you can use this activity instance inside the method.
Case 2
Pass Activity when initializing the object:
MyObj myObj = new MyObj(ActivityName.this);
Where Class will look like this:
class MyObj{
private Activity thisActivity;
public MyObj(Activity activity){
thisActivity = Activity;
}
...
}
Then you can use this activity instance.
When you have activity object available you can replace context object with it.

Callback When DialogFragment is Dismissed

I want to launch a dialog with a custom layout, which I've implemented via a DialogFragment. (I basically just changed onCreateView() and added button handlers). The dialog lets the user quickly change an important setting.
This dialog will be launched from several different activities. The different activities don't have much in common, except that they need to refresh after the user makes a change to the setting. They don't need to get any information from the dialog; they merely need to know when it's closed (dismissed).
What I've Tried
I tried having the activity refresh in onResume(), but launching and dismissing a dialog never seems to call this method. (So I'm not sure why it even exists, but that's probably a topic for another question.)
Next, I tried adding a DialogInterface.OnDismissListener to the dialog:
public static void showMyDialog(OnDismissListener listener, Activity activity)
{
DialogFragment fragment = new MyDialogFragment();
fragment.show(activity.getFragmentManager(), "date");
activity.getFragmentManager().executePendingTransactions();//A
fragment.getDialog().setOnDismissListener(listener);//B
}
When I originally left out the line A, I got a NullPointerException on line B because the dialog is null at that point. Following the advice of this SO answer, I put in the call to executePendingTransaction(). This causes an IllegalStateException on line B, with the message "OnDismissListener is already taken by DialogFragment and cannot be replaced." I also tried putting setOnDismissListener() before the call to show(), but that always caused a NullPointerException.
I then read this other SO answer, which says the original asker was "calling getDialog() too early in the DialogFragment's life cycle." So I tried adding a constructor to my DialogFragment:
public MyDialogFragment(SomeCallback illTakeAnythingICanGet)
{
//I'll store the callback here and call it later
}
Unfortunately, adding a constructor made Android Lint freak out with a fatal warning, and when I looked it up, I found a comment in this question that seems to say this approach will make it impossible to deal with the user rotating the screen while the dialog is open.
The Question
How can an activity figure out when a DialogFragment has closed (been dismissed) in a way that won't break my app if the user rotates the screen? Should I be using something else besides a DialogFragment?
This is just a longer explanation of harism's comment in case anyone else has the same problem I did.
You can accomplish what I wanted by creating an interface like this:
public interface MyDialogCloseListener
{
public void handleDialogClose(DialogInterface dialog);//or whatever args you want
}
Have the activity that launches your dialog (DialogFragment) implement this interface. Then give that DialogFragment the following method:
public void onDismiss(DialogInterface dialog)
{
Activity activity = getActivity();
if(activity instanceof MyDialogCloseListener)
((MyDialogCloseListener)activity).handleDialogClose(dialog);
}
More explanatory code for someone to do the same.
Create the interface as:
package com.example.dialoglistener;
import android.content.DialogInterface;
public interface MyDialogCloseListener {
public void handleDialogClose(DialogInterface dialog);
}
Implement the interface in activity as:
MyDialogCloseListener closeListener = new MyDialogCloseListener() {
#Override
public void handleDialogClose(DialogInterface dialog) {
//do here whatever you want to do on Dialog dismiss
}
};
Write a DismissListener in DialogFragement as
public void DismissListener(MyDialogCloseListener closeListener) {
this.closeListener = closeListener;
}
call DismissListener from your activity as:
dialogFragementObject.DismissListener(closeListener);
and finally write onDismiss method
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if(closeListener != null) {
closeListener.handleDialogClose(null);
}
}
Tyler's example was the only example I could find that actually worked. The only thing that needs changed for the example to work is the call to the DismissListner method in the DialogFragment class. He has it as:
dialogFragementObject.DismissListner(closeListener);
This just needs to be a cast to whatever your class name of that DialogFragment is. For example:
((MyDialogFragment)dialogFragementObject).DismissListner(closeListener);

Need Context when no activity is running

I am displaying a pop up from Notification of my application.But when I check my notification no activity is running from my application so in notification when I show dialogue. Dialogue throws exception because no activity is running and context which I am passing to dialogue constuctor is null therefore I need a context when no activity is running thanks in advance. Or any Idea how I can implement this thanks in advance
you can make your dialog extend and Activity class and change its theme to dialog in the manifest file. in this case, you call notification.setLatestEventInfo(YourActivityDialog.this, contentTitle, contentText, contentIntent);.
I suffered with the same issue. I can't able to use the spinner in my activity. I solved this by using the setContentView like as following
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
View viewToLoad = LayoutInflater.from(this.getParent()).inflate(R.layout.main, null);
this.setContentView(viewToLoad);
}
Another way you can use the separate activity for you dialog. By setting activity like follows
style.xml
<resources>
<style name="AppTheme" parent="android:Theme.Dialog">
<item name="android:windowNoTitle">true</item>
</style>
</resources>
In AndroidManifest Declare activity like this
<activity
android:name="DialogActivity"
android:theme="#style/AppTheme" />
#Override
protected Dialog onCreateDialog(int i)
{
LayoutInflater factory = LayoutInflater.from(this);
final View textEntryView = factory.inflate(R.layout.sendemail, null);
final View textEntryView1 = factory.inflate(R.layout.sendemail_title, null);
to_id = (EditText) textEntryView.findViewById(R.id.edit_text_sender_mail_id);
from_id =(EditText) textEntryView.findViewById(R.id.id);
pwd =(EditText) textEntryView.findViewById(R.id.pwd);
return new AlertDialog.Builder(current_activity.this)
.setTitle("hello")
.setCustomTitle(textEntryView1)
.setView(textEntryView)
.setPositiveButton("Send", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton)
{
// code here...
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
System.exit(0);
}
})
.create();
}
You may create MyApplication class, inherited from the Application, then inside that class do the following:
public class MyApplication extends Application {
private static MyApplication instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
.........
}
public static Context getContext() {
return instance;
}
After that, you may use MyApplication.getContext() anywhere if you need a context and don't have an Activity lying around.
I would assume that your code is running in a background in an Android Service. If that's the case, your Service is a Context itself, so you can use it when you need one.
Of your code is running in a background thread and not in an Android Service (in which case you have other big problems), you could use an instance of the application context. You get one though calling Context.getApplicationContext, and you can get it in the Activity that starts your background code and cache it for later.
Note though that there are certain gotchas with using application context, instead of activity context - for example, you can't use LayoutInflater from application context.

passing this to an outer class and starting an activity from alertdialog's list on Android

I am developing an Android app, this app has a dozen of Activities, each one is for a corresponding screen. Now I have this common subtitle bar on top of the screens.
this subtitle bar has a button to display an alert dialog which shows link list to go to a different screen.
I could write a same function for each activity to call the alert dialog, but that would be tedious if I want to modify them, so I created this class:
public class MenuAlertDialog extends Activity {
/*
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
*/
public void createMenu(final Context context){
AlertDialog.Builder dlg = new AlertDialog.Builder(context);
dlg.setTitle("menu");
String[] items = {"pageA", "pageB", "pageC", "pageD", "pageE"};
dlg.setItems(items, new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which){
switch(which){
case 0:
Intent intent = new Intent(context, MainActivity.class);
startActivity(intent);
break;
default:
break;
}
}
});
dlg.show();
}
}
and call it from each activity, like this:
MenuAlertDialog menu = new MenuAlertDialog();
menu.createMenu(this);
from inside of onCreate.
It can display the alertDialog, but whenever I press pageA link, it fails with an unexpected error.
Logcat says its a nullpointererror and the cause seems
startActivity(intent);
What am I doing wrong?
Remove the code
extends Activity
as you have no need to extend your class that you are creating since it does not rely on any activity related functionality.
Where you call startActivity(intent); replace it with
context.startActivity(intent);
You should change the class to Extends Dialog and not activity.
Also for Try this:
Check out this tutorial on how to create a custom dialog. Custom Dialog
Also Here Another Tutorial
And Here

Problem creating a custom dialog

I have a problem creating a custom dialog. But I don't find the failure. Hopefully anybody can help me ...
protected Dialog onCreateDialog(int id) {
Dialog dialog = null;
switch (id) {
case DIALOG_ABOUT_ID:
dialog = buildAboutDialog();
break;
default:
dialog = null;
}
return dialog;
}
...
public Dialog buildAboutDialog() {
Context mContext = getApplicationContext();
Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.about_dialog);
dialog.setTitle("About this application");
return dialog;
}
Results in the following error:
12-30 19:27:02.593: ERROR/AndroidRuntime(383): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
I checked if the returned dialog == null - but it isn't.
I also tried the second way (inflater) described at http://developer.android.com/guide/topics/ui/dialogs.html#CustomDialog
I found out, that the dialog needs to be created with
Dialog dialog = new Dialog(this);
and not
Context mContext = getApplicationContext();
Dialog dialog = new Dialog(mContext);
I don't exactly know why. Perhaps anybody can explain it to me?
Dialog dialog = new Dialog(contex);
dialog.setContentView(R.layout.help_content);
this works for me .. may be getapplicationcontext not getting context of the your main class.
As it turns out, Context of an activity is different then object returned by getApplicationContext(). This you can check by using logging, just output ActivityName.this and getApplicationContext.
The object returned by getApplicationContext is a global thing while context of an activity, well, belongs to that activity only.
Log.e(tag,""+ getApplicationContext());
Log.e(tag,""+CustomDialogActivity.this);
where CustomDialogActivity is my activity in which I want to show my dialog.
Dialogs require context of an activity and getApplicationContext() does not provide that. As written here (read comments) context of an activity is superset of getApplicationContext(). so It is a good thing to always pass context of an activity rather then the global context.
Also to answer ffleandro's comment of this page if you are inside onClick() you can use
ActivityName.this to refer to activity. Hope this helps

Categories

Resources