Question

I want my android app to display a pop-up window when the internet connection lost in order to tells the user that he lost the connection, I tried to catch null stream and then initiate a pop-up then, but it gives me that exception:

03-20 10:16:35.015: W/System.err(2922): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? 03-20 10:16:35.016: W/System.err(2922): at android.view.ViewRootImpl.setView(ViewRootImpl.java:646) 03-20 10:16:35.016: W/System.err(2922): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248) 03-20 10:16:35.016: W/System.err(2922): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 03-20 10:16:35.016: W/System.err(2922): at android.widget.PopupWindow.invokePopup(PopupWindow.java:993) 03-20 10:16:35.016: W/System.err(2922): at android.widget.PopupWindow.showAtLocation(PopupWindow.java:847) 03-20 10:16:35.016: W/System.err(2922): at android.widget.PopupWindow.showAtLocation(PopupWindow.java:811) 03-20 10:16:35.016: W/System.err(2922): at com.example.solaceap.Login$5.run(Login.java:135) 03-20 10:16:35.016: W/System.err(2922): at android.app.Activity.runOnUiThread(Activity.java:4662) 03-20 10:16:35.016: W/System.err(2922): at com.example.solaceap.Login.init_conn_lost_popup(Login.java:119) 03-20 10:16:35.016: W/System.err(2922): at com.example.solaceap.Login$6$1.run(Login.java:281) 03-20 10:16:35.016: W/System.err(2922): at android.os.Handler.handleCallback(Handler.java:725) 03-20 10:16:35.017: W/System.err(2922): at android.os.Handler.dispatchMessage(Handler.java:92) 03-20 10:16:35.017: W/System.err(2922): at android.os.Looper.loop(Looper.java:153) 03-20 10:16:35.017: W/System.err(2922): at android.app.ActivityThread.main(ActivityThread.java:5299) 03-20 10:16:35.017: W/System.err(2922): at java.lang.reflect.Method.invokeNative(Native Method) 03-20 10:16:35.017: W/System.err(2922): at java.lang.reflect.Method.invoke(Method.java:511) 03-20 10:16:35.017: W/System.err(2922): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) 03-20 10:16:35.017: W/System.err(2922): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) 03-20 10:16:35.017: W/System.err(2922): at dalvik.system.NativeStart.main(Native Method)

I don't know is the app crashed before running or that because as I'm not in the inflated activity at that time, And this is my code:

Worth to mention that the stream is got from a normal java class that implements Runnable not an activity class, as I just ran a thread that keeps giving me Input data from the stream , look at that :

    public String getServerResponse() throws JSONException {

        String responseLine, server_response = null_string;

        InputStream stream = null;
        try{
        stream = socket.getInputStream();
        }catch(Exception e){
            e.printStackTrace();
            Login login = new Login();
            login.init_conn_lost_popup();
        }

        if(stream != null){
            input = new BufferedReader(new InputStreamReader(
                    stream));
        try {
            while ((responseLine = input.readLine()) != null){
                server_response = server_response + responseLine;       
            }
        } catch (IOException e) {
            Login.errorMessage.setText(conn_err);
        }

    }
    return null;
}

And then in the activity that ran the past thread at the first:

Thread run_time = new Thread() {
        @Override
        public void run() {

            ConnectToServer connect = new ConnectToServer(); // this is the Runnable class
            while (true) {
                String server_response = null;
                try {
                    server_response = connect.getServerRespons(Login.this);
                } catch (Exception e1) {
                }
                try {
                    if (!server_response.equals(null)) {
                    }
                } catch (Exception e) {
                    if (!this.isInterrupted()) {
                        flag = true;
                        runOnUiThread(new Runnable() {
                            public void run() {
                                flag = false;
                                init_conn_lost_popup();
                            }
                        });

                    }
                }
            }

        }
    };
    run_time.start();

And this is the pop_up method :

public void init_conn_lost_popup() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            try {
                LayoutInflater inflater = (LayoutInflater) Login.this
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                View layout = inflater.inflate(R.layout.connection_popup,
                        (ViewGroup) findViewById(R.id.conn_pop));

                // create a 300px width and 470px height PopupWindow
                final PopupWindow pw = new PopupWindow(layout,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT, true);
                // display the popup in the center
                pw.showAtLocation(layout, Gravity.CENTER, 0, 0); // this is where i'm getting the Exception
        }
    });

}

And I just made a lot of tries like :

  • Replacing the inflater with :

    getWindow().addContentView(layout,new ViewGroup.LayoutParams (ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)); // after declaring the Layout View of course

  • Changing the context (Login.this) to :

1- getApplicationContext().

2- getBaseContext().

3- creating an Application class to retrieve the context from then called the desired method (MyApplication.getAppContext()).as explained here.

Was it helpful?

Solution

Instead of creating popup functionality into activity itself,try to create the seperate activity for it and when internet connection gone,call this activity and while declaring that activity into android manifest file use the following tag

android:theme="@style/Theme.Transparent" 

so that you will not get the error even if you are not into application

OTHER TIPS

why don't you just register broadcast receiver, that will notify you when connection is lost? It would be more easier, than that you do now.

private final BroadcastReceiver connectionStateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (!isNetworkAvailable(context)) {
            init_conn_lost_popup();
        }
    }
}

privaate boolean isNetworkAvailable(final Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

and now just register this receiver in onResume() method, also unregister it in onPause()

//Declare your AlertDialog here
    private AlertDialog alertDialog;
    .....
    .....
//Your Broadcasr receiver in Mainactivity for connection change info     
    private BroadcastReceiver networkReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                    NetworkInfo networkInfo = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
                    if (networkInfo != null && networkInfo.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
                        try {
                            if (alertDialog != null && alertDialog.isShowing())
                                alertDialog.dismiss();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else if (networkInfo != null && networkInfo.getDetailedState() == NetworkInfo.DetailedState.DISCONNECTED) {
                        if (alertDialog == null || !alertDialog.isShowing()) {
                            AlertDialog.Builder builder = new AlertDialog.Builder(context);
//Define your custom layout here
                            LayoutInflater inflater = getLayoutInflater();
                            View dialoglayout = inflater.inflate(R.layout.dialog_networl_lost, null);
                            builder.setView(dialoglayout);
                            builder.setCancelable(false);
                            alertDialog = builder.create();
                            alertDialog.show();
                        }
                    }
                }
            }
        };

        @Override
        protected void onResume() {
            super.onResume();
            IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
            registerReceiver(networkReceiver, intentFilter);
        }

        @Override
        protected void onPause() {
            super.onPause();
            if (networkReceiver != null)
                unregisterReceiver(networkReceiver);
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top