I have a spinner in my android app and I can get it to show but the sec. I click it, the app crashes and throws :
Unable to add Window -- token android.view.ViewRootImpl$Wfb# is not valid: is your activity running?
The layout is simple. I have an activity that has a list and a button to add something to the list. When clicked, the add button open a popup window that displays the spinner, a text box and a button. Everything works fine till I click the spinner .
Now I've searched google for an hour and found these:
Android - Dynamically Adding values to Spinners
BadTokenException Unable to add Window Spinner in PopUpWindow
Android Spinner Error : android.view.WindowManager$BadTokenException: Unable to add window
and more. They all seem to point to the context, however I've tried everything from using "this", to getApplicationContext, to the name of my activity.context and none of it works. I tried using the answer someone provided twice instead of just setting the contentView to the page and that made things worse (the app crashed with a null pointer exception right away).
Here's the code for the popup window (executed when the "add" button is clicked):
public void add_itinerary_clicked(View view)
{
LayoutInflater i = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = i.inflate(R.layout.itinerary_add_item_page, null);
popup = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
popup.showAtLocation(popupView , Gravity.CENTER, 0, 0);
Spinner airlineChoice = (Spinner) popupView.findViewById(R.id.airlineSpinner);
Button addBtn= (Button) popupView.findViewById(R.id.finish_addItinerary);
String[] list = new String[1];
list = airlineMap.keySet().toArray(list);
ArrayAdapter<CharSequence> spinnerAdapter = new ArrayAdapter<CharSequence>(getApplicationContext(), android.R.layout.simple_spinner_item, list );
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
airlineChoice.setAdapter(spinnerAdapter);
addBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish_addItinerary_clicked();
popup.dismiss();
}
});
}
I'm completely at a loss at this point. If it's not the context (I've tried what others have said) then what is it?
Here's the complete error message:
FATAL EXCEPTION: main
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W#40de1700 is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:567)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:246)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:993)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:899)
at android.widget.ListPopupWindow.show(ListPopupWindow.java:603)
at android.widget.Spinner$DropdownPopup.show(Spinner.java:981)
at android.widget.Spinner.performClick(Spinner.java:609)
at android.view.View$PerformClick.run(View.java:17355)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
I think you should not be using the application context, but the activity context.
Use a dialog and not a popup. It's easier, less code to maintain, and the standard according to Google.
I think there needs to be some sort of click listener on the spinner.
Thanks to Buggie, I have found a work around. I'm using a dialog instead. It works and doesn't throw an error. I'm not sure why this works and a popup window doesn't but here's my code that works:
public void add_itinerary_clicked(View view)
{
dialog = new Dialog(this);
dialog.setContentView(R.layout.itinerary_add_item_page);
Spinner airlineChoice = (Spinner) dialog.findViewById(R.id.airlineSpinner);
Button addBtn= (Button) dialog.findViewById(R.id.finish_addItinerary);
String[] list = new String[1];
list = airlineMap.keySet().toArray(list);
ArrayAdapter<CharSequence> spinnerAdapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, list );
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
airlineChoice.setAdapter(spinnerAdapter);
airlineChoice.setOnItemSelectedListener(this);
addBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish_addItinerary_clicked();
dialog.dismiss();
}
});
dialog.show();
}
One thing you might try is using your activity context, rather than your application/base context. This might help the situation.
Related
I have a maintenance application, where the operator does a checklist, and the previous steps are disabled, but I need to be able to go back to the previous step, and I would like to do this in an alertDialog
I created a setOnLongClickListener and I'm getting the View, and trying to add in alertDialog, but I get the exception that the layout has a parent (), when I remove View with, removeView (), it works, but I can't remove the View of princiapal activity
passo1.setOnLongClickListener(v -> {
dialogBuilder = new AlertDialog.Builder(initManutencao.this);
if (v.getParent() != null){
((ViewGroup) v.getParent()).removeView(v);
}
dialogBuilder.setView(v);
alertDialog = dialogBuilder.create();
alertDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
alertDialog.show();
//disableItens.ShowItensScren(0, initManutencao.this);
return false;
});
In short, I need to copy a LinearLayout with all its contents to an alertDialog, without me removing it from the main activity when I press it.
Main Activity, should not be changed
wanted but without removing LinearLayout from the main activity
I have a dialog in my launcher activity that requires some user input and to display it I have this code in onCreate()...
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog);
DialogBinding dialogBinding = DataBindingUtil.setContentView(this, R.layout.dialog);
popupBinding.dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.show();
The dialog button has an onClick listener to close it, but in order to do that, the dialog must be declared final. Previously (when this activity was not the launcher), I had the dialog declared as an instance variable, but this causes an error now.
private Dialog dialog = new Dialog(this);
However, declaring the dialog in the onCreate method causes the launcher activity's layout to be replaced with the dialog's so that the dialog appears over a copy of itself.
I'm not sure why it is doing that, but I was wondering if there is a way to prevent this. Thanks!
This accidentily sets the dialog layout as the content view for your activity.
DialogBinding dialogBinding = DataBindingUtil.setContentView(this, R.layout.dialog);
So you're mixing your activity with the dialog.
For your Activity, this should be something like
MyActivityBinding activityBinding = DataBindingUtil.setContentView(this, R.layout.my_activity);
Answer
The answer / an example can be found at the bottom of this post. The way this answer has been reached, can be found in this answer and its comments.
Original question
I've got a dialogFragment, which has two editText input fields. On a specific buttonClick, I want this dialogFragment to be created, and the two editText fields to be filled with text. For this purpose, I created a simple method inside the dialogFragment's class.
public void presetFields(String nameField, String tagField) {
nameInputField.setText(nameField);
tagInputField.setText(tagField);
}
Problem is, that both nameInputField and tagInputField get initialised inside the onCreateDialog method.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
final View v_iew = inflater.inflate(R.layout.fragment_inputdialog, null);
nameInputField = (EditText) v_iew.findViewById(R.id.inputdialogname);
tagInputField = (EditText) v_iew.findViewById(R.id.inputdialogtag);
}
I thought that would be no problem at all, since I have a similar construction running for a fragment. Only difference is that the editText's get initialised in an onCreateView instead of an onCreateDialog.
This is the onClick code that shows the dialogFragment and calls the method to set the nameInputField and tagInputField fields.
editButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stuffManagerInputDialogFragment.show(getFragmentManager(), "TEST");
stuffManagerInputDialogFragment.presetFields(nameTextViewContent, tagTextViewContent);
}
});
When I click the editButton, this is the log I get with the NPE
03-02 16:04:25.120 509-509/com.example.tim.timapp I/art: Not late-enabling -Xcheck:jni (already on)
03-02 16:04:25.190 509-509/com.example.tim.timapp W/System: ClassLoader referenced unknown path: /data/app/com.example.tim.timapp-2/lib/x86_64
03-02 16:04:25.400 509-524/com.example.tim.timapp D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
03-02 16:04:25.520 509-524/com.example.tim.timapp I/OpenGLRenderer: Initialized EGL, version 1.4
03-02 16:04:25.570 509-524/com.example.tim.timapp W/EGL_emulation: eglSurfaceAttrib not implemented
03-02 16:04:25.570 509-524/com.example.tim.timapp W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x7fceb5b27dc0, error=EGL_SUCCESS
03-02 16:04:28.660 509-509/com.example.tim.timapp D/TEST: 2131493026
03-02 16:04:30.310 509-509/com.example.tim.timapp D/AndroidRuntime: Shutting down VM
03-02 16:04:30.310 509-509/com.example.tim.timapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tim.timapp, PID: 509
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference
at com.example.fragments.MainFragments.DialogFragments.StuffManagerInputDialogFragment.presetFields(StuffManagerInputDialogFragment.java:149)
at com.example.fragments.MainFragments.VariableFragments.StuffManagerVariableFragment$2.onClick(StuffManagerVariableFragment.java:87)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
03-02 16:04:33.140 509-509/com.example.tim.timapp I/Process: Sending signal. PID: 509 SIG: 9
I'm not an expert by far, but what I make of this error, is that nameTextView and tagTextView are null at the moment that I'm trying to set text to them, which makes me think the method gets called before the fragment is created.
How can I make sure that both editText's are properly initialised before I try to call something on it?
I have removed some bits of code for easy reading. If something seems to be missing, it probably is. Please let me know, so I can add it.
If you require more code, please also let me know.
Complete answer
All credits go to George Mulligan for this one.
So some stuff has changed from the original approach. First of all, the presetFields method has been removed. The text that should populate the editText fields is now passed to the fragment as an argument.
The onClick method now looks like this:
editButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
nameTextViewContent = nameTextView.getText().toString();
tagTextViewContent = tagTextView.getText().toString();
Bundle args = new Bundle();
args.putString("name", nameTextViewContent);
args.putString("tag", tagTextViewContent);
stuffManagerInputDialogFragment.setArguments(args);
stuffManagerInputDialogFragment.show(getFragmentManager(), "TEST");
}
});
So without the presetFields method, we have no way to set the editText fields to the text we want. This has been added to the onCreateDialog method, as can be seen below.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
final View v_iew = inflater.inflate(R.layout.fragment_inputdialog, null);
nameInputField = (EditText) v_iew.findViewById(R.id.inputdialogname);
tagInputField = (EditText) v_iew.findViewById(R.id.inputdialogtag);
if (getArguments() != null) {
nameInputField.setText(getArguments().getString("name"));
tagInputField.setText(getArguments().getString("tag"));
}
}
The null-check for getArguments() has been added because I sometimes need to call this dialogFragment without filling the editText fields. When this happens, it means there are no arguments set to the fragment, which would result in a NPE when calling getArguments().getString("String");
That should be it. I do however have a reputation for being stupid, so it might very well be possible I overlooked something, that should be included in this explanation. If so, please let me know, so I can add it.
What I make of this error, is that nameTextView and tagTextView are
null at the moment that I'm trying to set text to them, which makes me
think the method gets called before the fragment is created.
That is almost correct. The Fragment is created but onCreateDialog() has not been called yet because showing the dialog happens asynchronously after the call to show(...).
You can fix this by adding the two preset Strings as arguments to the DialogFragment.
You can then assign the EditText fields the correct value directly in the onCreateDialog method by using getArguments() on the DialogFragment.
Here is what this looks like:
public MyDialogFragment extends DialogFragment {
private static final String ARG_NAME = "name";
private static final String ARG_TAG = "tag";
public MyDialogFragment newInstance(String name, String tag) {
Bundle args = new Bundle();
args.putString(ARG_NAME, name);
args.putString(ARG_TAG, tag);
MyDialogFragment frag = new MyDialogFragment();
frag.setArguments(args);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
final View v_iew = inflater.inflate(R.layout.fragment_inputdialog, null);
nameInputField = (EditText) v_iew.findViewById(R.id.inputdialogname);
tagInputField = (EditText) v_iew.findViewById(R.id.inputdialogtag);
nameInputField.setText(getArguments().getString(ARG_NAME, ""));
tagInputField.setText(getArguments().getString(ARG_TAG, ""));
}
}
Then the new click event handler.
editButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stuffManagerInputDialogFragment = MyDialogFragment
.newInstance(nameTextViewContent, tagTextViewContent);
stuffManagerInputDialogFragment.show(getFragmentManager(), "TEST");
}
});
Don't try to manipulate your dialog immediately after calling show.
If you want to set default values for fields within your dialog, pass them to the dialog as arguments and initialise them during the dialog creation.
e.g
public class MyFragment extends Fragment {
/**
* Static factory method that takes an int parameter,
* initializes the fragment's arguments, and returns the
* new fragment to the client.
*/
public static MyFragment newInstance(int index) {
MyFragment f = new MyFragment();
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
}
from: http://www.androiddesignpatterns.com/2012/05/using-newinstance-to-instantiate.html
I am new to android programming and I am trying to create a simple home screen replacement/launcher using a viewpager.
When I try to run the application, it starts up and then immediately force closes. I think it is something to do with a null pointer exception but I am really new to programming and can't find the source of the error.
This is my logcat.
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dntmdp.matthewhuckel.simplephonelauncher/com.dntmdp.matthewhuckel.simplephonelauncher.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
// etc...
Caused by: java.lang.NullPointerException
at com.dntmdp.matthewhuckel.simplephonelauncher.MainActivity.onCreate(MainActivity.java:47)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
// etc...
08-13 20:10:58.585 1805-1805/com.dntmdp.matthewhuckel.simplephonelauncher I/Process﹕ Sending signal. PID: 1805 SIG: 9
This is my main activity java class.
public class MainActivity extends ActionBarActivity {
Button phone;
// more buttons
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageButton phone = (ImageButton) findViewById(R.id.imageButton);
phone.setOnClickListener(new View.OnClickListener() { // Exception thrown on this line
#Override
public void onClick(View view) {
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.android.phone");
startActivity(LaunchIntent);
}
});
//setting more onclicklisteners in exactly the same manner
MyPagerAdapter adapter = new MyPagerAdapter();
ViewPager myPager = (ViewPager) findViewById(R.id.viewpager_layout);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
}
// menu initialization
}
I found the answer. I was trying to find the image button id's in the activity_main xml, but they were in other activities.
I am quite new to Java and Android programming, and just working on my 3rd App - however I am encountering a Problem which I am not able to solve (I already tried and researched for days).
I have a list of Elements in a LinearLayout inside a Fragment - the Elements have a OnLongClickListener attached, with a popup showing up when the User long-presses the Element. That works fine. However, one of the Buttons in the Popup is "Edit", and when a user presses this Button, I want to start another Activity with Editing Options for this Element.
So there comes my Problem: when I want to start the new Activity with an Intent, I get following Error:
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at android.app.Activity.startActivityForResult(Activity.java:3370)
at android.app.Activity.startActivityForResult(Activity.java:3331)
at android.app.Activity.startActivity(Activity.java:3566)
at android.app.Activity.startActivity(Activity.java:3534)
at at.fekle.zipmanager.start.startzipinfo(start.java:299)
at at.fekle.zipmanager.start$2.onLongClick(start.java:277)
at android.view.View.performLongClick(View.java:4247)
at android.view.View$CheckForLongPress.run(View.java:17341)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5227)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
But, if i start the same Activity with the same Intent from a simple Button defined in the Layout, the Activity Starts fine without any Errors... weird, isn't it?
So, does anyone have an Idea how I can solve this problem?
Here are some extractions from my code:
The Creation of the Elements with the OnLongClickListener:
ScrollView parent = (ScrollView) maininflater.inflate(R.layout.start_ziplist_fragment_superwrapper, null, false);
inf = maininflater;
LinearLayout ll = (LinearLayout) maininflater.inflate(R.layout.start_ziplist_fragment_wrapper, parent, false);
for (Integer i = 0; i < count; i++) {
ArrayList<String> data = new DB(cont).getAllZips().get(i);
View custom = maininflater.inflate(R.layout.start_ziplist_fragment_inner, ll, false);
TextView tv = (TextView) custom.findViewById(R.id.ziplist_name);
TextView tv2 = (TextView) custom.findViewById(R.id.ziplist_text);
tv.setText(data.get(2));
tv2.setText(data.get(1));
Integer id = Integer.valueOf(data.get(0));
custom.setId(id);
custom.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
Integer id = view.getId();
startzipinfo(id);
return true;
}
});
ll.addView(custom);
}
parent.addView(ll);
The void which starts the Activity:
public void startzipinfo(Integer id){
Intent in = new Intent(getApplicationContext(), zipinfo.class);
startActivity(in);
}
I'm looking forward to your Answers,
Felix
EDIT: This is the Activity which is about to be started:
package at.fekle.zipmanager;
import android.app.Activity;
import android.os.Bundle;
/**
* Created by felix on 27.06.13.
*/
public class zipinfo extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.zipinfo);
}
}
Try to use YourActivityName.this instead of getApplicationContext() :
public void startzipinfo(Integer id){
Intent in = new Intent(YourActivityName.this, zipinfo.class);
startActivity(in);
}
Check whether your new intent class is mentioned in android manifest file if it does not exists then type:<activity name=".YourClassName>
</activity>
I just solved the problem!
I had to start the activity from the parent Fragment (passed to the method by the FragmentManager) - now everything works like a charm :)
custom.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
Integer id = view.getId();
id = 2;
Intent intent = new Intent(cont, zipinfo.class);
fragment.startActivity(intent);
return true;
}
});
Thanks for all answers!
Cheers,
Felix