I have an app that uses three Activities. I've created in the first one a Thread that checks the connection with the server and when the app cant reach the server it shows a Popup.
The thing is that when I go from the Activity1 to the Activity2 and I lose the connection, I'm getting a WindowManager$BadTokenException.
I've tried with PopupWindow and with AlertDialog but I have the same problem, I can't give them the current Activity.
Alert Dialog:
AlertDialog.Builder builder1 = new AlertDialog.Builder(getApplicationContext());
builder1.setMessage("Se ha hecho el cierre diario, es necesario reiniciar la aplicaciĆ³n.");
builder1.setCancelable(true);
builder1.setPositiveButton("Ok",
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
java.lang.System.exit(0);
}
});
AlertDialog alert11 = builder1.create();
alert11.show();
PopupWindow:
final Activity context = Activity_Start.this;
final boolean Reset = reset;
// Inflate the popup_layout.xml
LinearLayout viewGroup = (LinearLayout) context.findViewById(R.id.popup_mensaje_error);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View popup_error = layoutInflater.inflate(R.layout.mensaje_error, viewGroup, false);
// Creating the PopupWindow
final PopupWindow popupW_error = new PopupWindow(context);
popupW_error.setContentView(popup_error);
In both cases I have the same error and I'm almost 100% sure that is cause getApplicationContext() is no enough to get what the app needs.
Can someone help me? Thanks!!
Android documents suggests to use getApplicationContext();
but it will not work instead of that use your current activity while instantiating AlertDialog.Builder or AlertDialog or Dialog...
Try
AlertDialog.Builder builder1 = new AlertDialog.Builder(Activity_Start.this);
instead of
AlertDialog.Builder builder1 = new AlertDialog.Builder(getApplicationContext());
And also use
final Context context = Activity_Start.this;
instead of
final Activity context = Activity_Start.this;
The dialog is tied to this particular activity, and not the entire application. Generally use Activity.this when creating objects whose scope is just the activity. Use Application context when you are creating objects whose scope is beyond the current activity.
Hope this helps!
Related
I definied my own method to display Toast and I want to call it from another Activity. When I do that, my app crash. Do you have some Attempt to invoke virtual method.... on a null object reference.
The Toast method:
public void showToastDown(Context context, String message) {
context = getApplicationContext();
inflater = getLayoutInflater();
View v = inflater.inflate(R.layout.toast_down, (ViewGroup) findViewById(R.id.toast_down_root));
TextView tvToastDown = v.findViewById(R.id.tvToastDown);
tvToastDown.setText(message);
Toast toast = new Toast(context);
toast.setGravity(Gravity.BOTTOM|Gravity.FILL_HORIZONTAL, 0,0);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(v);
toast.show();
}
and the code from 2nd activity:
switch (item.getItemId()){
case R.id.btnAddActionBar:
MainActivity mainActivity= new MainActivity();
mainActivity.showToastDown(this, "TEXT");
break;
}
return super.onOptionsItemSelected(item);
}
Remove this line from your code, as you are already passing value of context so no need to initialize again with Application Context.
context = getApplicationContext();
EDIT: Change Your Method like this:
public void showToastDown(Context context, String message) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
View v = inflater.inflate(R.layout.toast_down, (ViewGroup) ((Activity)context).findViewById(R.id.toast_down_root));
TextView tvToastDown = v.findViewById(R.id.tvToastDown);
tvToastDown.setText(message);
Toast toast = new Toast(context);
toast.setGravity(Gravity.BOTTOM|Gravity.FILL_HORIZONTAL, 0,0);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(v);
toast.show();
}
There's a couple of problems with your code:
Never instantiate activities yourself (mainActivity = new MainActivity). This doesn't work, only the Android OS can create activities. I suggest taking some (free) beginner android tutorials online to understand how activities work and what their role is.
The toast function you've written is a utility function that doesn't appear to have anything to do with MainActivity. If you put it as a static function of a different class (whose purpose is only to provide useful utility functions like this) e.g. ActivityTools.java, then you can call it from anywhere and pass it a Context like you are doing.
In your toast function, you're receiving a context as the first parameter but then immediately overwriting it. This doesn't make any sense, there's no reason to overwrite it like this.
I am checking the internet connection in my application, when the internet is not accessible I want to display a small popup message to the user that you're offline.
I tried to solve the issue by using AlertDialog and AlertDialog.Builder, and I have also searched through different solution on the internet but no solution resolve my issue. I am trying to do this by the following method.
AlertDialog.Builder builder = new AlertDialog.Builder(context);
LayoutInflater inflater = LayoutInflater.from(context);
View alertdialog = inflater.inflate(R.layout.nointernetdialogue, null);
builder.setView(alertdialog);
AlertDialog dialog = builder.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
WindowManager.LayoutParams alertTop = dialog.getWindow().getAttributes();
alertTop.gravity = Gravity.TOP | Gravity.START;
alertTop.x = 100;
alertTop.y = 100;
dialog.show();
The result I want.
Create BaseActivity which shall implement Broadcast Receiver regarding network connectivity checks. Whenever network connectivity goes off, show the SnackBar/Alert.
Let all your other activities extend this Base activity.
Alert dialog looks like a over kill just have a TextView and show and hide it on network change.
Try with this example Click here
here i am using BroadcastReceiver to find the Wifi and Mobile data status
By this you can access the Network state anywhere un the App
You should create a BaseActivity that checks internet connection and shows alert dialog if needed. All activities that you want to show alert dialog should extended from BaseActivity.
You can work with top SnackBar , there is the code
Snackbar snack = Snackbar.make(findViewById(android.R.id.content), "Online", Snackbar.LENGTH_LONG);
View view = snack.getView();
FrameLayout.LayoutParams params =(FrameLayout.LayoutParams)view.getLayoutParams(); params.gravity = Gravity.TOP;
view.setLayoutParams(params);
snack.show();
I have some codes like this:
ArrayList<Teacher> teachers = subs.get(position).getTeachers();
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View v = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_layout, null);
builder.setView(v);
ListView listViewDialog = (ListView) v.findViewById(R.id.dialog_lv);
TesAdapter adapter1 = new TesAdapter(MainActivity.this, teachers);
listViewDialog.setAdapter(adapter1);
adapter1.notifyDataSetChanged();
listViewDialog.setDivider(null);
builder.show();
This operation takes a lot of time. So, I am trying to show a ProgressDialog while it is loading. then to hide the progressbar and show this AlertDialog.
I have tried these:
How to show progress dialog in Android?
How can I run code on a background thread on Android?
But none of them worked :( any solution?
So I've got a Dialog, which contains some editText fields (these are spread over 3 fragments, shown by a viewpager, in case this info matters). For an edit action, I want to create that dialog with some values already put in.
At the moment I'm trying to do it like this:
editButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
GeneralSettingsInitialInputDialog GSIID = new GeneralSettingsInitialInputDialog();
Bundle args = new Bundle();
args.putString("name", TitleTV.getText().toString());
args.putString("ip", IPaddressET.getText().toString());
args.putString("port", PortET.getText().toString());
args.putString("username", UsernameET.getText().toString());
args.putString("pass", PasswordET.getText().toString());
Log.d(tag, args.toString());
GSIID.setArguments(args);
GSIID.show(((Activity) context).getFragmentManager(), "GSIID");
This shows the onClickListener for the edit button (which is contained in a recyclerView. This particular bit comes from my Adapter).
After that, I tried this in the onCreateDialog method for the GSIID dialogFragment:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
ma = (MainActivity) getActivity();
dbHandler = DBHandler.getInstance(getActivity());
view = inflater.inflate(R.layout.fragment_generalsettingsviewpager, null);
mPager = (ViewPager) view.findViewById(R.id.pager);
mPager.setOffscreenPageLimit(3);
mPagerAdapter = new TestAdapter();
mPager.setAdapter(mPagerAdapter);
if (getArguments() != null) {
((EditText) view.findViewById(R.id.IDName)).setText(getArguments().getString("name"));
((EditText) view.findViewById(R.id.IDIPaddress)).setText(getArguments().getString("ip"));
((EditText) view.findViewById(R.id.IDPort)).setText(getArguments().getString("port"));
((EditText) view.findViewById(R.id.IDUsername)).setText(getArguments().getString("username"));
((EditText) view.findViewById(R.id.IDPassword)).setText(getArguments().getString("pass"));
}
// Build Dialog
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setView(view)
.setTitle("Setup Device")
.setMessage("Please add all required details for your Raspberry Pi here.")
.setPositiveButton("Next", null)
.setNegativeButton("Cancel", null);
return builder.show();
}
This returned a NPE, saying I was trying to use setText on a null, so view.findViewById() is returning null. I thought I'd fix that by moving this code to the onStart() method, to make sure everything is there before I try to set stuff on it, but I'm still getting the same error.
All this time, I'm noticing that the dialog does NOT open before the error occurs, so I'm guessing the findViewById() method is still called too soon, but I don't know how to fix that.
I have tested to make sure my code is not broken, by having the above code run when a button on the GSIID dialog is pressed (so the dialog is opened then). This did indeed work.
So, basically: How can I prevent this findViewById method from being called too early?
Most likely by looking up views in onCreateView() by calling the lookups on the view you're returning from this method.
You need to master the life-cycle of an Activity in android this link and this link can help you to understand the sequence of function calls in each step of the life-cycle.
In most cases you have your views in onCreatView() so it is reasonable to put your findViewById there but in other cases you should make sure the view has been inflated before you call findViewById
Well, my day is saved, thanks to this post.
Basically, you just need a method inside your custom PagerAdapter that returns the view for the index you give it.
CustomAdapter
New: Constructor (I believe that's what it's called)
private View view0 = null;
private View view1 = null;
private View view2 = null;
private View viewError = null;
public TestAdapter(LayoutInflater inflater) {
view0 = inflater.inflate(R.layout.fragment_generalsettingsinputdialog1, null);
view1 = inflater.inflate(R.layout.fragment_generalsettingsinputdialog2, null);
view2 = inflater.inflate(R.layout.fragment_generalsettingsinputdialog3, null);
viewError = inflater.inflate(R.layout.fragment_viewpagererror, null);
}
Changed: instantiateItem()
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View instView = getViewAtPosition(position);
instView.setTag("layoutThingy"+position);
container.addView(instView);
instView.requestFocus();
return instView;
}
New: getViewAtPosition()
public View getViewAtPosition(int position) {
View view = null;
switch(position) {
case 0:
view = view0;
break;
case 1:
view = view1;
break;
case 2:
view = view2;
break;
default:
view = viewError;
}
return view;
}
Other stuff
When initialising PagerAdapter, make sure you pass a LayoutInflater as an argument. For me it was like this: mPagerAdapter = new TestAdapter(getActivity().getLayoutInflater());
Now, I did this in my onStart() method, but I'm guessing you can do this pretty much everywhere.
View page1 = mPagerAdapter.getViewAtPosition(0);
View page2 = mPagerAdapter.getViewAtPosition(1);
View page3 = mPagerAdapter.getViewAtPosition(2);
if (getArguments() != null) {
((EditText) page1.findViewById(R.id.IDName)).setText(getArguments().getString("name"));
((EditText) page2.findViewById(R.id.IDIPaddress)).setText(getArguments().getString("ip"));
((EditText) page2.findViewById(R.id.IDPort)).setText(getArguments().getString("port"));
((EditText) page3.findViewById(R.id.IDUsername)).setText(getArguments().getString("username"));
((EditText) page3.findViewById(R.id.IDPassword)).setText(getArguments().getString("pass"));
}
This properly finds all my EditText's, and should properly find everything I put in my ViewPager. Great! Thanks all for trying to help me, and of course a big thank you to cYrixmorten, with his great post.
Right, I know there's alot of similar questions. I've researched on stackoverflow as well as on the internet about this but still stumped.
This code is in a fragment.
...
private Context context = getActivity();
public void Dialog(){
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
View mView = inflater.inflate(R.layout.dialog, null);
alertDialogBuilder.setView(mView);
EditText a = (EditText) mView.findViewById(R.id.a);
EditText b = (EditText) mView.findViewById(R.id.b);
EditText c = (EditText) mView.findViewById(R.id.c);
//a.setText("abc");
//b.setText("xyz");
//c.setText("123");
strA = a.getText().toString();
strB = b.getText().toString();
final String strC = c.getText().toString();
}
This should be a typical approach to getting the view of the inflated layout and using it to access the elements inside the view, but it's not working no matter what I tried, I just could not get strA, strB and strC values using getText().toString().
//a.setText("abc");
//b.setText("xyz");
//c.setText("123");
But, if I uncomment the above 3 lines, the values get sent across. And I can receive them inside strA, strB, strC. Why is this so? I don't get it at all.
Any help greatly appreciated, thank you!
You are trying to get values at the time you initialize the dialog. you need to get values after an action, like a button click
alertDialogBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
strA = a.getText().toString();
strB = b.getText().toString();
}
});
Have a look at this display textview in alert dialog
Looks to me like you're checking the values of the EditTexts as soon as they're created. Which of course the value is going to be null every time since your user hasn't had time to type anything. I think you need a SubmitButton or something similar that checks the EditTexts in its onClickListener. Though I'll admit I've never inflated a view into an alert dialog.
Try like this.
MyDialogue is your Activity name.
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MyDialogue.this);
// Get the layout inflater
LayoutInflater inflater = MyDialogue.this.getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
View mView = inflater.inflate(R.layout.dialog, null);
alertDialogBuilder.setView(mView);
final EditText a = (EditText) mView.findViewById(R.id.a);
final EditText b = (EditText) mView.findViewById(R.id.b);
final EditText c = (EditText) mView.findViewById(R.id.c);
a.setText("abc");
b.setText("xyz");
c.setText("123");
alertDialogBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
final String strA = a.getText().toString();
final String strB = b.getText().toString();
final String strC = c.getText().toString();
Log.e("tag", strA + " " + strB + " " + strC );
}
});
alertDialogBuilder.show();
The layout is not yet initiated when you are trying to set the values, you need to call AlertDialog alertDialog = alertDialogBuilder.create(); and then alertDialog.show(); or just alertDialogBuilder.show() before you can edit the textView content.