首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
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

Stack Overflow用户

发布于 2021-07-01 13:57:11

我决定检查解决方案这里,并做了一些改进和示例。我还让它避免了相同值的多次设置,这样就不会使观察者一个接一个地得到相同的值:

ConnectionLiveData.kt

代码语言:javascript
运行
复制
class ConnectionLiveData(private val context: Context) : LiveData<Boolean>() {
    private val handler = Handler(Looper.getMainLooper())
    private lateinit var connectivityManagerCallback: ConnectivityManager.NetworkCallback
    private lateinit var networkReceiver: BroadcastReceiver

    init {
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> {
                connectivityManagerCallback = object : ConnectivityManager.NetworkCallback() {
                    @AnyThread
                    override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                            networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                            setNewValue(true)
                        }
                    }

                    override fun onAvailable(network: Network) {
                        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1)
                            setNewValue(true)
                    }

                    override fun onLost(network: Network) {
                        setNewValue(false)
                    }
                }
            }
            else -> {
                networkReceiver = object : BroadcastReceiver() {
                    override fun onReceive(context: Context, intent: Intent) {
                        updateConnection()
                    }
                }
            }
        }
    }

    /**this prevents observers to get multiple times the same value*/
    @AnyThread
    private fun setNewValue(isConnected: Boolean) {
        handler.removeCallbacksAndMessages(null)
        if (isUiThread()) {
            if (value != isConnected)
                @SuppressLint("WrongThread")
                value = isConnected
            return
        }
        handler.post {
            if (value != isConnected)
                value = isConnected
        }
    }

    @UiThread
    override fun onActive() {
        super.onActive()
        val connectivityManager: ConnectivityManager = context.getSystemService()!!
        updateConnection()
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> connectivityManager.registerDefaultNetworkCallback(connectivityManagerCallback, handler)
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> connectivityManager.registerDefaultNetworkCallback(connectivityManagerCallback)
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
                val networkRequest =
                    NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build()
                connectivityManager.registerNetworkCallback(networkRequest, connectivityManagerCallback)
            }
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> {
                val networkRequest =
                    NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build()
                connectivityManager.registerNetworkCallback(networkRequest, connectivityManagerCallback)
            }
            else -> {
                @Suppress("DEPRECATION") context.registerReceiver(networkReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
            }
        }
    }

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


    @Suppress("DEPRECATION")
    private fun updateConnection() {
        setNewValue(isConnectedToInternet(context))
    }

    companion object {
        @JvmStatic
        fun isUiThread(): Boolean =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) Looper.getMainLooper().isCurrentThread else Thread.currentThread() === Looper.getMainLooper().thread

        private fun isConnectedToInternet(context: Context): Boolean {
            val connectivityManager: ConnectivityManager = context.getSystemService()!!
            val activeNetwork: NetworkInfo? = connectivityManager.activeNetworkInfo
            return activeNetwork?.isConnectedOrConnecting == true
        }
    }
}

MainActivity.kt

代码语言:javascript
运行
复制
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView = findViewById<TextView>(R.id.textView)
        ConnectionLiveData(this).observe(this) {
            textView.text = if (it) "connected" else "disconnected"
            Log.d("AppLog", "connected?$it")
        }
        val internetSettings = findViewById<View>(R.id.internetSettings)
        internetSettings.isVisible = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
        internetSettings.setOnClickListener {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
                startActivity(Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY))
        }
        findViewById<View>(R.id.wifiSettings).setOnClickListener {
            startActivity(Intent(Settings.ACTION_WIFI_SETTINGS))
        }
        findViewById<View>(R.id.mobileDataSettings).setOnClickListener {
            startActivity(Intent(Settings.ACTION_DATA_ROAMING_SETTINGS))
        }
    }
}

activity_main.xml

代码语言:javascript
运行
复制
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"
    android:orientation="vertical" tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" />

    <Button
        android:id="@+id/internetSettings" android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="internet settings" />

    <Button
        android:id="@+id/wifiSettings" android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="wifi settings" />

    <Button
        android:id="@+id/mobileDataSettings" android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="mobile-data settings" />
</LinearLayout>

清单要求:

代码语言:javascript
运行
复制
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

请注意,当飞机模式打开时,它有一个罕见的问题,即它暂时认为没有连接,然后相反,但又返回到没有连接。报道了这个这里

票数 1
EN
查看全部 15 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36421930

复制
相关文章

相似问题

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