-1

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.

Community
  • 1
  • 1
MRefaat
  • 515
  • 2
  • 8
  • 22
  • try this way: `View layout = inflater.inflate(R.layout.connection_popup, (ViewGroup) youractivity.this.findViewById(R.id.conn_pop));` – M D Mar 20 '14 at 08:55
  • that gives me an Exception failed to connect to socket – MRefaat Mar 20 '14 at 09:01
  • You can't in general make this work in android as the lifetime cycle of an activity is a bit complicated - take a look at autocrab's answer which is more 'android' than your solution – Elemental Mar 20 '14 at 09:37

3 Answers3

3

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

asiya
  • 280
  • 1
  • 5
  • 16
  • this one is good , but I face a problem with it as i can't navigate to the Activity by `Intent` as i need the app context which i think it's already destroyed before getting in that. `Intent menuIntent = new Intent(MyApplication.getAppContext(), Connection_popup.class); startActivity(menuIntent);` – MRefaat Mar 20 '14 at 12:01
  • so you have to use getApplicationcontext() – asiya Mar 24 '14 at 07:16
2

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()

Autocrab
  • 3,474
  • 1
  • 15
  • 15
0
//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);
        }