简体   繁体   English

在运行时检查互联网连接是否丢失

[英]Checking if the internet connection is lost at runtime

Good day. 美好的一天。 I know how to check if there is an internet connection available, my problem is that I want to present the user an AlertDialog that prevents action except trying again whenever the connection is lost or deactivated. 我知道如何检查是否有可用的Internet连接,我的问题是我想向用户显示一个AlertDialog,该警报对话框将阻止操作,除非在连接丢失或停用时再次尝试。 What I don't know is how to code it only one time, so I don't need to replicate it manually in all activities. 我不知道如何只编写一次代码,所以我不需要在所有活动中手动复制它。

I tried using Observer Pattern, and initialize it in SplashActivity(Launcher Activity). 我尝试使用观察者模式,并在SplashActivity(Launcher Activity)中对其进行了初始化。


 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        ObservedObject observedObject = new ObservedObject();
        observedObject.addObserver(new ObserverInternetConnection());

}
 public class ObservedObject extends Observable {
        private boolean isConnected;

        public boolean isConnected() {
            return isConnected;
        }

        public void setConnected(boolean connected) {
            isConnected = connected;
            setChanged();
            notifyObservers();
        }

     public class ObserverInternetConnection implements Observer {

        @Override
        public void update(Observable observable, Object o) {
            if (observable instanceof ObservedObject) {
                if (observable.hasChanged())
//alert is a method to show toast message
                    alert("connection changed");
                if (((ObservedObject) observable).isConnected)
                    alert("connected");
                else
                    alert("disconnected");

            }

        }
    }

It worked when I manually set the observedObject connection. 当我手动设置observedObject连接时,它起作用了。 But I want to avoid doing so. 但我想避免这样做。 Is there a way to do this automatically? 有没有一种方法可以自动执行此操作? I was thinking of using another thread, but how could I do so? 我当时在考虑使用另一个线程,但是我该怎么做呢? another problem is that the way i check the internet connection is using ConnectivityManager but it need me to pass the context and the context can (and will) change throughout the application, how can I overcome so? 另一个问题是,我检查Internet连接的方式是使用ConnectivityManager,但它需要我传递上下文,并且上下文可以(并且将会)在整个应用程序中发生变化,我该如何克服呢? Is there any other approach for the problem? 还有其他解决方法吗?

I would suggest to create BaseActivity where you are initializing connectivity change listener (Observer in your case) and extend this activity with Splash, Main and other activities that you are using. 我建议在初始化连接更改侦听器(在您的情况下为Observer)的地方创建BaseActivity ,并使用Splash,Main和其他正在使用的活动扩展此活动。

This way you are going to avoid code duplication. 这样,您将避免代码重复。

Also don't forget to unregister listeners when activity is destroyed. 当活动被破坏时,也不要忘记注销监听器。

Also you dont need to use different threads. 另外,您不需要使用其他线程。 Here is example how to listen connectivity changes in Activity: 这是如何在Activity中监听连接性变化的示例:

Register receiver first: 首先注册接收者:

   @Override
    public void register(Context context) {
        initReceiver();
        final IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        context.registerReceiver(receiver, intentFilter);
    }

receiver 接收器

receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (isOnline()) {
                    hideNoConnectionError();
                } else {
                    showNoConnectionError();
                }
            }
        };

and isOnline() 和isOnline()

 val isOnline: Boolean
        get() {
            return try {
                val connectivityManager = context.getSystemService(
                        Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                connectivityManager.activeNetworkInfo != null &&
                        connectivityManager.activeNetworkInfo.isConnected
            } catch (exception: Exception) {
                false
            }
        }

sorry, last method is written in Kotlin, but I think it is completely understandable 抱歉,最后一种方法是用Kotlin编写的,但是我认为这完全可以理解

One additional approach if your minimal SDK version >= N(24) would be to subscribe to ConectivityManager in Application class. 如果您的最低SDK版本> = N(24),另一种方法是在Application类中订阅ConectivityManager In order to prevent user from interaction start transparrent activity on top with some shadowed background stating that connection lost. 为了防止用户进行交互,请在顶部启动透明活动,并用一些阴影背景说明该连接已丢失。 This is not ideal approach but you will not need to stick to inheritance. 这不是理想的方法,但是您无需坚持继承。

TestApplication.java TestApplication.java

public class TestApplication extends android.app.Application {
    private static final String TAG = "TestApplication";
    @Override
    public void onCreate() {
        super.onCreate();

        ConnectivityManager m = (ConnectivityManager) getSystemService(Service.CONNECTIVITY_SERVICE);
        m.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                Log.e(TAG, "onAvailable: ");
                startActivity(ConnectionLostScreen.createIntentHideSplashOnNetworkRecovery(TestApplication.this));
            }

            @Override
            public void onLost(Network network) {
                Log.e(TAG, "onLost: ");
                startActivity(ConnectionLostScreen.createShowSplashOnNetworkFailure(TestApplication.this));
            }

        });
    }
}

ConnectionLostScreen.java ConnectionLostScreen.java

public class ConnectionLostScreen extends AppCompatActivity {
    private final static int SHOW = 1;
    private final static int HIDE = 2;
    private final static String EXTRA_NAME = "ACTION";

    public static Intent createShowSplashOnNetworkFailure(Context app) {
        Intent intent = new Intent(app, ConnectionLostScreen.class);
        intent.putExtra(EXTRA_NAME, SHOW);
        intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT| Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_ANIMATION);
        return intent;
    }

    public static Intent createIntentHideSplashOnNetworkRecovery(Context app) {
        Intent intent = new Intent(app, ConnectionLostScreen.class);
        intent.putExtra(EXTRA_NAME, HIDE);
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        return intent;
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);

        if (getIntent() != null) handleIntent(getIntent());
    }

    @Override
    public void onBackPressed() {
       //disabled so user would not be able to close this activity.
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if (intent != null) handleIntent(intent);
    }

    void handleIntent(Intent intent) {
        int value = intent.getIntExtra(EXTRA_NAME, 0);

        if (value == 0 || value == HIDE) {
            finish();
            return;
        }
    }
}

Theme for ConnectionLostScreen would be. ConnectionLostScreen的主题为。

<style name="Theme.Transparent" parent="AppTheme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>

Pros: 优点:

  • No inheritance. 没有继承。
  • Independent and works across application 独立且跨应用程序工作
  • No activity lifetime tracking 没有活动生命周期跟踪
  • No need for Activity context as entire Activity acts like dialog. 不需要Activity上下文,因为整个Activity就像对话框一样。
  • Custom layout, graphic, animation could be integrated 自定义布局,图形,动画可以集成
  • No user action needed because when connection restored ConnectionLostScreen will be closed. 无需用户操作,因为恢复ConnectionLostScreen时, ConnectionLostScreen将关闭。

Cons: 缺点:

  • Activity flow management for ConnectionLostScreen (making it singleTop etc.) ConnectionLostScreen活动流管理(使其变为singleTop等)
  • Hard to make granular control if only certain screens should be covered 如果仅应覆盖某些屏幕,则很难进行精细控制
  • Animations for Activity transitions 活动过渡的动画

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM