Android strange behavior on orientation change wit

2019-07-01 22:43发布

问题:

I have a FragmentActivity which shows a Fragment by defualt. The fragment consists of an EditText, a TextView and a Custom DropDown, made by extending AutoCompleteTextView. If my custom AutoCompleteTextView is focused or the drop down list is open and I change the orientation of the device. I get following exception:

Failed Looking up window
java.lang.IllegalArgumentException: Requested window null does not exist

It works if the custom AutoCompleteTextView is not in focused state. I've tried removing the focus in onSaveInstanceState() by making other layout get focus by requestFocus() I've searched for this on the internet for more then 2 days, and it seems that no one has faced such issue before regarding Custom Views in context of fragments and orientation change.

Here is my FragmentActivity:

public class Balance_Inquiry extends FragmentActivity implements OnTouchListener, EventCallbackListener, DataCallBack,CustomResultReceiver.Receiver  {

LinearLayout balInquiryLayout;
FragmentTransaction fragmentTransaction;
FragmentManager fm;
Fragment fr;

//SQLiteDatabase sql;
//ConDb db;

public final static int ACTIVITY_ID = 2;
private Bundle orientationData;



protected void onCreate(Bundle savedInstanceState){

    try{
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    DisplayMetrics metrics = getResources().getDisplayMetrics();
    int screenWidth = (int) (metrics.widthPixels * 0.90);

    setContentView(R.layout.common_blank_dialog);
    //Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(App.context()));

    getWindow().setLayout(screenWidth, LayoutParams.WRAP_CONTENT);

    balInquiryLayout = (LinearLayout) findViewById(R.id.dialogtoplayout);
    orientationData = savedInstanceState;
    if(savedInstanceState == null){
        fr = new Balance_Main_Fragment();
         fm = getSupportFragmentManager();
         fragmentTransaction = fm.beginTransaction();
         fragmentTransaction.setCustomAnimations(R.anim.zoom_enter, R.anim.zoom_exit);
         fragmentTransaction.add(R.id.dialogtoplayout, fr,"tag1");
         fragmentTransaction.commit();
    }
    else{
         fr = getSupportFragmentManager().findFragmentByTag("tag1");
    }


    balInquiryLayout.setOnTouchListener(this);
    }
    catch(Exception e){
        e.printStackTrace();
    }

}

@Override
public boolean onTouch(View v, MotionEvent event) {

    balInquiryLayout.requestFocus();
    DisableKeyboard.hideKB(v, getApplicationContext());
    return false;
}




private AccountBean ab_;
private ValuesBean resp_;




public void show_result(){
    try{
      fr = new Balance_Result_Fragment();
         fm = getSupportFragmentManager();
         fragmentTransaction = fm.beginTransaction();
         fragmentTransaction.setCustomAnimations(R.anim.zoom_enter, R.anim.zoom_exit);
         fragmentTransaction.add(R.id.dialogtoplayout, fr, "tag2");
         fragmentTransaction.commit();
    }

    catch(Exception e){
        e.printStackTrace();
    }
}


public void hideResult(){


      fr = new Balance_Result_Fragment();
         fm = getSupportFragmentManager();
    fragmentTransaction = fm.beginTransaction();
    fragmentTransaction.setCustomAnimations(R.anim.zoom_exit,R.anim.zoom_enter);
    fragmentTransaction.remove(fr).commit();


    //new Balance_Main_Fragment().clearAll();

}



@Override
public void onButtonClicked(int a) {


    switch(a){

            case 0:
                {


                    hideResult();

                    try{


                          fm = getSupportFragmentManager();
                          Balance_Main_Fragment fre=(Balance_Main_Fragment)getSupportFragmentManager().findFragmentByTag("tag1");
                             fre.clearAll();

                         fre.enableButtons();
                         }
                         catch(Exception e){
                             e.printStackTrace();
                         }

                    break;
                }

            case 1:
            {
                show_result();
                break;
            }


    }

}







@Override
public void passData(String... a) {


}







@Override
public void passData(Object... a) {
    try{
     this.ab_=(AccountBean) a[0];
     this.resp_ = (ValuesBean) a[1];     
     }
    catch(ClassCastException e){
        e.printStackTrace();
    }


}







@Override
public Object[] getData() {
    // TODO Auto-generated method stub
    return new Object[]{this.ab_,this.resp_};
}

@Override
public void onBackPressed(){
    if(MainExpandActivity.backApprove== true){
        if(ParserMain.isMyServiceRunning(MessengerService.class, this)){
        NetworkThread.stopServiceNow(Balance_Inquiry.this);
        NetworkThread.unBindServicePlz(Balance_Inquiry.this);
        }
        super.onBackPressed();
    }
    else{
        // do nothing here hehehehe
    }

}

@Override
public void onReceiveResult(int resultCode, final Bundle resultData) {
    Log.e("activity", "activties onRecieveresul is called");
}

public void onDestroy(){
    //NetworkThread.unBindServicePlz(Balance_Inquiry.this);
    super.onDestroy();
    Log.e("onDestory()", "onDestory() is called");
    if(isFinishing()){
        NetworkThread.unBindServicePlz(this.getApplicationContext());
        NetworkThread.stopServiceNow(this.getApplicationContext());
        Log.e("onDestory()", "isFinishing() block");
    }

}

public void onWindowFocusChanged(boolean hasFocus) {

    super.onWindowFocusChanged(hasFocus);

  if(hasFocus) 
     Toast.makeText(Balance_Inquiry.this, "focus gained", Toast.LENGTH_LONG).show();

  else
      Toast.makeText(Balance_Inquiry.this, "focus lost", Toast.LENGTH_LONG).show();
}



public void onPause(){
    Log.e("onPause()", "pause called");
    balInquiryLayout.requestFocus();

    super.onPause();

    }

}

Following is my Fragment class, posting only relevant snippets from it:

InstantAutoComplete accounts;  // custom View
LinearLayout balInq2ndLayout;
@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    setRetainInstance(true);

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    main_view = inflater.inflate(R.layout.fragment_balance1, container,false);
    sub = (Button) main_view.findViewById(R.id.sub_bal);

    cancel = (Button) main_view.findViewById(R.id.cancel_bal);

    accounts = (InstantAutoComplete) main_view.findViewById(R.id.bal_accounts);

    mHat = new Handler();
    balInq2ndLayout = (LinearLayout) main_view.findViewById(R.id.balInq2ndLayout);
    balInq2ndLayout_2 = (LinearLayout) main_view.findViewById(R.id.balInq2ndLayout_2);


    macBalance = (TextView) main_view.findViewById(R.id.macbal_balinq);

    macBalance.setText(SessionInfo.getBalanceString()+SessionInfo.getMacBalance());
    bal_prog = (TextView) main_view.findViewById(R.id.bal_status);

    pb = (ProgressBar) main_view.findViewById(R.id.progressBarBalance);
    pb.setVisibility(View.GONE);
    balInq2ndLayout.requestFocus();
    balInq2ndLayout.setOnTouchListener(this);
    balInq2ndLayout_2.setOnTouchListener(this);

    pin_no = (EditText) main_view.findViewById(R.id.bal_pin);

    bal_accountLocked = (EditText) main_view.findViewById(R.id.bal_accountlocked);

    bal_accountLocked.setEnabled(false);
    bal_accountLocked.setFocusable(false);
    bal_accountLocked.setVisibility(View.GONE);


    myData = new Bundle();

    if(savedInstanceState==null){

    bal_accountLocked.setVisibility(View.GONE);


    }
    else{

        pin_no.setText(savedInstanceState.getString("pin"));

        if(savedInstanceState.getBoolean("key")){
            bal_accountLocked.setVisibility(View.VISIBLE);
            bal_accountLocked.setText(savedInstanceState.getString("locked"));
        }


        if(accounts.getText().toString().length()!=0){
            ab = savedInstanceState.getParcelable("ab");
        }

        if(savedInstanceState.getBoolean("progress")){

            pb.setVisibility(View.VISIBLE);
            disableButtons();
        }

        accounts.setText(savedInstanceState.getString("account"));

    }




    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(App.context()));

    final ArrayAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.select_dialog_item, ObjectsHolder.ab);
    accounts.setAdapter(adapter);

    accounts.setOnFocusChangeListener(new OnFocusChangeListener() {

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(!hasFocus){
                if(accounts.getText().length()==0){
                //Toast.makeText(getActivity(), "focus lost", Toast.LENGTH_LONG).show();
                accounts.setText(saved1);
                DisableKeyboard.disableSoftInputFromAppearing(accounts, getActivity());

                    }
                }
            else if(hasFocus){
                DisableKeyboard.disableSoftInputFromAppearing(accounts, getActivity());
            }

        }
    });

    accounts.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            DisableKeyboard.disableSoftInputFromAppearing(accounts, getActivity());
            saved1=DisableKeyboard.showAll(accounts);
            if(accounts.getText().toString().length()==0){
                bal_accountLocked.setText("");
                bal_accountLocked.setVisibility(View.GONE);
            }
            return false;
        }
    });



    accounts.setOnItemClickListener(new AdapterView.OnItemClickListener() {
          @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id){
                Log.e("inside setOnItemSelectedListener", "this is called normally");
                //Toast.makeText(arg0.getContext(), "On item click: "+arg0.getItemAtPosition(arg2), 1).show();
                ab= (AccountBean) adapter.getItem(position);

                //ab = (AccountBean) arg0.getItemAtPosition(arg2);
                if(ab==null){
                    Log.e("ab object", "is null :(");
                }
                else{
                    bal_accountLocked.setVisibility(View.VISIBLE);
                    bal_accountLocked.setText(ab.getAccountNumber());
                }
                //saved1 = (String) arg0.getItemAtPosition(arg2);
    }

    });

    return main_view;

}

@Override
public boolean onTouch(View v, MotionEvent event) {
    balInq2ndLayout.requestFocus();
    DisableKeyboard.hideKB(v, getActivity());
    return false;
}


    public void onSaveInstanceState(Bundle state){
      super.onSaveInstanceState(state);
      Log.e("onSaved", "onSaved is  called");
      balInq2ndLayout.requestFocus(); // setting request here to LinearLayout
      if(bal_accountLocked.isShown()){
      state.putString("locked", bal_accountLocked.getText().toString());
      state.putBoolean("key", true);
      }
      if(ab!=null){
        state.putParcelable("ab", ab);
      }
      state.putString("pin", pin_no.getText().toString());

      if(pb.getVisibility() == View.VISIBLE){
        state.putBoolean("progress", true);
        state.putBoolean("back", true);
      }

      if(accounts.getText().toString().length()!=0){
        state.putString("account", accounts.getText().toString());
      }

  }

Finally This is my custom AutoCompleteTextView

import android.content.Context;  
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.AutoCompleteTextView;


public class InstantAutoComplete extends AutoCompleteTextView {
String savedTexti2;

public InstantAutoComplete(Context context) {
    super(context);
}

public InstantAutoComplete(Context arg0, AttributeSet arg1) {
    super(arg0, arg1);
}

public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) {
    super(arg0, arg1, arg2);
}

@Override
public boolean enoughToFilter() {
    return true;
}

@Override
protected void onFocusChanged(boolean focused, int direction,
        Rect previouslyFocusedRect) {
    super.onFocusChanged(focused, direction, previouslyFocusedRect);
    if (focused) {
        performFiltering(getText(), 0);
        showAll();
    }
    else{
        //Toast.makeText(getContext(), "works", 10).show();
        //restore();
    }

}


public void restore() {
    this.setText(savedTexti2);
}

public void showAll() {
    savedTexti2 = this.getText().toString();
    this.setText("");
    this.showDropDown();
    }





}

Here is the complete StackTrace:

Failed looking up window
java.lang.IllegalArgumentException: Requested window null does not exist at com.android.server.WindowManagerService.windowForClientLocked(WindowManagerService.java:9293) at com.android.server.WindowManagerService.addWindow(WindowManagerService.java:1891) at com.android.server.WindowManagerService$Session.add(WindowManagerService.java:6771) at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:66) at com.android.server.WindowManagerService$Session.onTransact(WindowManagerService.java:6743)
at android.os.Binder.execTransact(Binder.java:288) at dalvik.system.NativeStart.run(Native Method) Attempted to add window with token that is not a window: null. Aborting.

I've tried many different things, like removing focus from the AutoCompleteTextView , switching focus.. but nothing seems to work. If anyone can help me I would be grateful as I've visited each and every corner of stackoverflow but no luck. If someone has faced this issue and managed to solve it, please help a brother here.

--EDIT--

This issue was produced in emulator of API 8

Tested it on Emulator of JellyBean API 17 and it works fine. No exception. I wonder if its only related to lower APIs. Have to check them all one by one. sigh