检查网络连接的Android服务?

10

我想创建一个 Android 服务,当断开连接和重新连接到互联网时,通知主活动。我有以下用于检查互联网连接性的函数:

private boolean haveInternet(){
        NetworkInfo info=(NetworkInfo)((ConnectivityManager)this.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();

        if(info==null || !info.isConnected()){
            return false;
        }
        if(info.isRoaming()){
            //here is the roaming option you can change it if you want to disable internet while roaming, just return false
            return true;
        }
        return true;
    }

但是我想知道,如何在服务中使用它。

2个回答

28

服务被设计用于长时间后台运行任务。 您应该使用BroadcastReceiver

这是一个我用来监控网络状态并在我的主 Activity 中使用的示例方法:

private void installListener() {

        if (broadcastReceiver == null) {

            broadcastReceiver = new BroadcastReceiver() {

                @Override
                public void onReceive(Context context, Intent intent) {

                    Bundle extras = intent.getExtras();

                    NetworkInfo info = (NetworkInfo) extras
                            .getParcelable("networkInfo");

                    State state = info.getState();
                    Log.d("InternalBroadcastReceiver", info.toString() + " "
                            + state.toString());

                    if (state == State.CONNECTED) {

                        onNetworkUp();

                    } else {

                        onNetworkDown();

                    }

                }
            };

            final IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
            registerReceiver(broadcastReceiver, intentFilter);
        }
    }

在 onDestroy 事件发生时记得调用 unregisterReceiver。

希望能对你有所帮助。


太棒了!我喜欢你创建了一个方法,并添加了onNetworkUp和Down回调函数。 - Bhargav
2
我正在使用这个并且效果很好,但我想把它放在一个类或者监听器中。这样我就可以在多个活动中使用它,但我想避免重复编写代码。那么正确的做法是什么? - Nelson Silva
你好,请帮忙一下吗? - Nelson Silva
我按照@NelsonSilva的建议添加了一个带有类的答案。我相信这是一个起点,我们可以继续改进它。 - JCarlosR

0

这是一个Kotlin版本,遵循Francesco Laurita的解决方案:

private val broadcastReceiver by lazy {
    NetworkListener.create({
        btnOnlineVideos.visibility = View.VISIBLE
    }, {
        btnOnlineVideos.visibility = View.GONE
    })
}

override fun onResume() {
    super.onResume()

    NetworkListener.register(this, broadcastReceiver)
}

override fun onPause() {
    super.onPause()

    NetworkListener.unregister(this, broadcastReceiver)
}

为了使这个工作,我只需覆盖onResumeonPause方法,以注册和注销BroadcastReceiver这是如何工作的? 我创建了以下类来帮助初始化、注册和注销BroadcastReceiver。这样就不需要重复大部分样板代码了。
package com.programacionymas.app.services

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.os.Parcelable
import android.util.Log

object NetworkListener {

    fun create(onNetworkUp: () -> Unit, onNetworkDown: () -> Unit): BroadcastReceiver {
        return object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {

                intent.extras?.getParcelable<Parcelable>("networkInfo")?.let {
                    val info = it as NetworkInfo
                    val state: NetworkInfo.State = info.state

                    Log.d("BroadcastReceiver", "$info $state")
                    if (state === NetworkInfo.State.CONNECTED) {
                        onNetworkUp()
                    } else {
                        onNetworkDown()
                    }
                }

            }
        }
    }

    fun register(context: Context, broadcastReceiver: BroadcastReceiver) {
        val intentFilter = IntentFilter()
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        context.registerReceiver(broadcastReceiver, intentFilter)
    }

    fun unregister(context: Context, broadcastReceiver: BroadcastReceiver) {
        context.unregisterReceiver(broadcastReceiver)
    }

}

如果您只需要为其中一个状态执行语句,您也可以传递 null 匿名函数:

private val broadcastReceiver by lazy {
    NetworkListener.create(null, {
        toast(getString(R.string.check_your_internet))
        finish()
    })
}

create方法中将参数声明为可选的:

fun create(onNetworkUp: (()->Unit)?, onNetworkDown: (()->Unit)?): BroadcastReceiver {/* ... */}

同时,仅在将函数作为参数发送时调用它们:

if (state === NetworkInfo.State.CONNECTED) {
    onNetworkUp?.invoke()
} else {
    onNetworkDown?.invoke()
}

NetworkInfo 在 Android 10+ 上已被弃用。您应该更新实现以使用 ConnectivityManager.NetworkCallback - Panos Gr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接