丢失Internet连接时如何显示弹出窗口?

时间:2014-03-20 08:52:15

标签: java android multithreading applicationcontext

我希望我的Android应用程序在互联网连接丢失时显示一个弹出窗口,以告诉用户他丢失了连接,我试图捕获空流然后启动弹出窗口,但它给出了我那个例外:

  

03-20 10:16:35.015:W / System.err(2922):   android.view.WindowManager $ BadTokenException:无法添加窗口 -   令牌null无效;你的活动在运行吗?       03-20 10:16:35.016:W / System.err(2922):在android.view.ViewRootImpl.setView(ViewRootImpl.java:646)       03-20 10:16:35.016:W / System.err(2922):在android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)       03-20 10:16:35.016:W / System.err(2922):在android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)       03-20 10:16:35.016:W / System.err(2922):在android.widget.PopupWindow.invokePopup(PopupWindow.java:993)       03-20 10:16:35.016:W / System.err(2922):在android.widget.PopupWindow.showAtLocation(PopupWindow.java:847)       03-20 10:16:35.016:W / System.err(2922):在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):在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):在android.os.Handler.handleCallback(Handler.java:725)       03-20 10:16:35.017:W / System.err(2922):在android.os.Handler.dispatchMessage(Handler.java:92)       03-20 10:16:35.017:W / System.err(2922):在android.os.Looper.loop(Looper.java:153)       03-20 10:16:35.017:W / System.err(2922):在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)

我不知道应用程序在运行之前是否已崩溃,或者因为我当时没有处于膨胀的活动中,而且这是我的代码:

值得一提的是,流是从一个普通的java类中获取的,它实现了Runnable而不是一个活动类,因为我只是运行了一个不断给我输入数据来自流的线程,看看:

    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;
}

然后在第一个运行过去线程的活动中:

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

这是pop_up方法:

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
        }
    });

}

我刚做了很多尝试:

  • 用:{/ p>替换inflater

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

  • 将上下文(Login.this)更改为:

1- getApplicationContext()

2- getBaseContext()

3-创建一个Application类来检索当前称为所需方法的上下文(MyApplication.getAppContext())。正如here所述。

3 个答案:

答案 0 :(得分:3)

不是将弹出功能创建到活动本身,而是尝试为它创建单独的活动,当互联网连接消失时,调用此活动,并在将该活动声明为android清单文件时使用以下标记

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

这样即使您没有进入申请,也不会收到错误

答案 1 :(得分:2)

为什么不注册广播接收器,当连接丢失时会通知您?它会比现在更容易。

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

现在只需在onResume()方法中注册此接收器,同时在onPause()

中取消注册

答案 2 :(得分: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);
        }