首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ConnectivityManager.CONNECTIVITY_ACTION被否决

ConnectivityManager.CONNECTIVITY_ACTION被否决
EN

Stack Overflow用户
提问于 2016-04-05 09:12:02
回答 15查看 60.4K关注 0票数 115

在Android中,官方网站上提到“针对Android的应用程序不接收CONNECTIVITY_ACTION广播”。同时也提到了JobScheduler可以作为一种替代方案。但是JobScheduler并没有提供与CONNECTIVITY_ACTION广播完全相同的行为。

在我的Android应用程序中,我使用这个广播来了解设备的网络状态。我想知道在CONNECTING广播的帮助下,这个状态是CONNECTED还是CONNECTIVITY_ACTION,它最适合我的需求。

现在它已被废弃,有谁能建议我获得当前网络状态的替代方法吗?

EN

回答 15

Stack Overflow用户

回答已采纳

发布于 2016-04-06 10:05:10

不推荐的是后台应用程序接收网络连接状态更改的能力。

正如大卫·瓦赛尔所说,如果应用程序组件被实例化(而不是销毁),并且您有以编程方式注册接收方及其上下文,而不是在清单中这样做,您仍然可以得到连接更改的通知。

或者您可以使用NetworkCallback代替。特别是,对于连接状态的更改,您需要重写onAvailable

让我快速起草一个片段:

代码语言:javascript
运行
复制
public class ConnectionStateMonitor extends NetworkCallback {

   final NetworkRequest networkRequest;

   public ConnectionStateMonitor() {
       networkRequest = new NetworkRequest.Builder()
           .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
           .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
           .build();
   }

   public void enable(Context context) {
       ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
       connectivityManager.registerNetworkCallback(networkRequest, this);
   }

   // Likewise, you can have a disable method that simply calls ConnectivityManager.unregisterNetworkCallback(NetworkCallback) too.

   @Override
   public void onAvailable(Network network) {
       // Do what you need to do here
   }
}
票数 113
EN

Stack Overflow用户

发布于 2018-10-09 10:13:49

我将更新Sayem's的答案,为修复棉问题,它显示给我。

代码语言:javascript
运行
复制
class ConnectionLiveData(val context: Context) : LiveData<Boolean>() {

    private var connectivityManager: ConnectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager

    private lateinit var connectivityManagerCallback: ConnectivityManager.NetworkCallback

    private val networkRequestBuilder: NetworkRequest.Builder = NetworkRequest.Builder()
        .addTransportType(android.net.NetworkCapabilities.TRANSPORT_CELLULAR)
        .addTransportType(android.net.NetworkCapabilities.TRANSPORT_WIFI)

    override fun onActive() {
        super.onActive()
        updateConnection()
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> connectivityManager.registerDefaultNetworkCallback(getConnectivityMarshmallowManagerCallback())
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> marshmallowNetworkAvailableRequest()
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> lollipopNetworkAvailableRequest()
            else -> {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    context.registerReceiver(networkReceiver, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")) // android.net.ConnectivityManager.CONNECTIVITY_ACTION
                }
            }
        }
    }

    override fun onInactive() {
        super.onInactive()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            connectivityManager.unregisterNetworkCallback(connectivityManagerCallback)
        } else {
            context.unregisterReceiver(networkReceiver)
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private fun lollipopNetworkAvailableRequest() {
        connectivityManager.registerNetworkCallback(networkRequestBuilder.build(), getConnectivityLollipopManagerCallback())
    }

    @TargetApi(Build.VERSION_CODES.M)
    private fun marshmallowNetworkAvailableRequest() {
    connectivityManager.registerNetworkCallback(networkRequestBuilder.build(), getConnectivityMarshmallowManagerCallback())
    }

    private fun getConnectivityLollipopManagerCallback(): ConnectivityManager.NetworkCallback {
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           connectivityManagerCallback = object : ConnectivityManager.NetworkCallback() {
               override fun onAvailable(network: Network?) {
                   postValue(true)
               }

               override fun onLost(network: Network?) {
                   postValue(false)
               }
           }
           return connectivityManagerCallback
       } else {
           throw IllegalAccessError("Accessing wrong API version")
       }
    }

    private fun getConnectivityMarshmallowManagerCallback(): ConnectivityManager.NetworkCallback {
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
          connectivityManagerCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onCapabilitiesChanged(network: Network?, networkCapabilities: NetworkCapabilities?) {
                networkCapabilities?.let { capabilities ->
                    if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                        postValue(true)
                    }
                }
            }
            override fun onLost(network: Network?) {
                postValue(false)
            }
         }
         return connectivityManagerCallback
       } else {
         throw IllegalAccessError("Accessing wrong API version")
       }
    }

    private val networkReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            updateConnection()
        }
    }

    private fun updateConnection() {
        val activeNetwork: NetworkInfo? = connectivityManager.activeNetworkInfo
        postValue(activeNetwork?.isConnected == true)
    }
}

同样的用法:

代码语言:javascript
运行
复制
    val connectionLiveData = ConnectionLiveData(context)
    connectionLiveData.observe(this, Observer { isConnected ->
           isConnected?.let {
             // do job
           }
    })

顺便说一句谢谢sayem的解决方案。

票数 51
EN

Stack Overflow用户

发布于 2016-04-06 10:12:10

Android N的文档声明:

针对Android的应用程序不接收CONNECTIVITY_ACTION广播,即使它们有清单条目请求通知这些事件。在前台运行的应用程序仍然可以在主线程上侦听CONNECTIVITY_CHANGE,如果它们请求BroadcastReceiver通知的话。

这意味着,如果您的应用程序运行在前台,您仍然可以注册一个BroadcastReceiver,以便检测网络连接的变化。

票数 30
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36421930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档