在Android N中,官方网站上提到"针对Android N的应用不接收CONNECTIVITY_ACTION广播".并且还提到JobScheduler
可以用作替代方案.但是JobScheduler
它没有提供与CONNECTIVITY_ACTION
广播完全相同的行为.
在我的Android应用程序中,我使用此广播来了解设备的网络状态.我想知道,如果在该状态CONNECTING
或CONNECTED
的帮助下CONNECTIVITY_ACTION
广播和它是最适合我的要求.
现在它已被弃用,任何人都可以建议我获得当前网络状态的替代方法吗?
Amo*_*tir 86
将弃用的是后台应用程序接收网络连接状态更改的能力.
正如David Wasser所说,如果应用程序组件被实例化(未销毁)并且您已使用其上下文以编程方式注册接收器,而不是在清单中执行此操作,则仍可以获得有关连接更改的通知.
或者您可以使用NetworkCallback.特别是,您需要覆盖onAvailable以进行连接状态更改.
让我快速起草一个片段:
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
}
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*ser 23
Android N的文档指出:
针对Android N的应用不会收到CONNECTIVITY_ACTION广播,即使他们有明确的条目来请求通知这些事件.如果应用程序通过BroadcastReceiver请求通知,则在前台运行的应用程序仍然可以在其主线程上侦听CONNECTIVITY_CHANGE.
这意味着,BroadcastReceiver
如果您的应用程序在前台运行,您仍然可以注册,以便检测网络连接的变化.
Keb*_*bby 19
我将更新Sayem's
修复lint问题的答案向我展示.
class ConnectionLiveData(val context: Context) : LiveData<Boolean>() {
private var connectivityManager: ConnectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
private lateinit var connectivityManagerCallback: ConnectivityManager.NetworkCallback
override fun onActive() {
super.onActive()
updateConnection()
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> connectivityManager.registerDefaultNetworkCallback(getConnectivityManagerCallback())
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() {
val builder = NetworkRequest.Builder()
.addTransportType(android.net.NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(android.net.NetworkCapabilities.TRANSPORT_WIFI)
connectivityManager.registerNetworkCallback(builder.build(), getConnectivityManagerCallback())
}
private fun getConnectivityManagerCallback(): 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("Should not happened")
}
}
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)
}
}
Run Code Online (Sandbox Code Playgroud)
同样的用法:
val connectionLiveData = ConnectionLiveData(context)
connectionLiveData.observe(this, Observer { isConnected ->
isConnected?.let {
// do job
}
})
Run Code Online (Sandbox Code Playgroud)
顺便说一下,感谢你说出你的错觉.
Say*_*yem 15
请首先检查@Amokrane Chentir对Android N支持的回答.
对于那些想要支持所有api级别并在ui中观察它的人,请查看下面的代码.
NetworkConnection的LiveData:
class ConnectionLiveData(val context: Context) : LiveData<Boolean>(){
var intentFilter = IntentFilter(CONNECTIVITY_ACTION)
private var connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
private lateinit var networkCallback : NetworkCallback
init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
networkCallback = NetworkCallback(this)
}
}
override fun onActive() {
super.onActive()
updateConnection()
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> connectivityManager.registerDefaultNetworkCallback(networkCallback)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> {
val builder = NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI)
connectivityManager.registerNetworkCallback(builder.build(), networkCallback)
}
else -> {
context.registerReceiver(networkReceiver, intentFilter)
}
}
}
override fun onInactive() {
super.onInactive()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
connectivityManager.unregisterNetworkCallback(networkCallback)
} else{
context.unregisterReceiver(networkReceiver)
}
}
private val networkReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
updateConnection()
}
}
fun updateConnection() {
val activeNetwork: NetworkInfo? = connectivityManager.activeNetworkInfo
postValue(activeNetwork?.isConnectedOrConnecting == true)
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class NetworkCallback(val liveData : ConnectionLiveData) : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network?) {
liveData.postValue(true)
}
override fun onLost(network: Network?) {
liveData.postValue(false)
}
}
}
Run Code Online (Sandbox Code Playgroud)
在UI中观察(活动/片段):
val connectionLiveData = ConnectionLiveData(context)
connectionLiveData.observe(this, Observer {
// do whatever you want with network connectivity change
})
Run Code Online (Sandbox Code Playgroud)
基于@KebabKrabby 的回答:
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Context.CONNECTIVITY_SERVICE
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.ConnectivityManager.CONNECTIVITY_ACTION
import android.net.ConnectivityManager.EXTRA_NO_CONNECTIVITY
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.os.Build
import androidx.lifecycle.LiveData
class ConnectivityWatcher(
private val context: Context
): LiveData<Boolean>() {
private lateinit var networkCallback: ConnectivityManager.NetworkCallback
private lateinit var broadcastReceiver: BroadcastReceiver
override fun onActive() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
networkCallback = createNetworkCallback()
cm.registerDefaultNetworkCallback(networkCallback)
} else {
val intentFilter = IntentFilter(CONNECTIVITY_ACTION)
broadcastReceiver = createBroadcastReceiver()
context.registerReceiver(broadcastReceiver, intentFilter)
}
}
override fun onInactive() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
cm.unregisterNetworkCallback(networkCallback)
} else {
context.unregisterReceiver(broadcastReceiver)
}
}
private fun createNetworkCallback() = object : ConnectivityManager.NetworkCallback() {
override fun onCapabilitiesChanged(
network: Network,
networkCapabilities: NetworkCapabilities
) {
val isInternet = networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)
val isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)
postValue(isInternet && isValidated)
}
override fun onLost(network: Network) {
postValue(false)
}
}
private fun createBroadcastReceiver() = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isNoConnectivity = intent?.extras?.getBoolean(EXTRA_NO_CONNECTIVITY) ?: true
postValue(!isNoConnectivity)
}
}
}
Run Code Online (Sandbox Code Playgroud)
并且使用它与原始答案几乎相同(例如,如果从活动中观察):
ConnectivityWatcher(this).observe(this, Observer {
Log.i("*-*-*", "is internet available? - ${if (it) "Yes" else "No"}")
})
Run Code Online (Sandbox Code Playgroud)
几天前我遇到了同样的问题,我决定使用这个Android-Job库
此库使用JobSchedular
,GcmNetworkManager
并BroadcastReceiver
取决于运行该应用程序的Android版本.
开始工作相当容易
new JobRequest.Builder(DemoSyncJob.TAG)
.setRequiresCharging(true)
.setRequiresDeviceIdle(false)
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED) // this is what gets the job done
.build()
.schedule();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
34164 次 |
最近记录: |