android - 我正在尝试检查互联网连接,但我的代码可能有问题,我无法弄清楚?
问题描述
所以我在这个简单的 android 应用程序中工作,我想检查互联网连接(并基于此我想显示缓存数据或只是从 API 中获取内容)但它不能按预期工作,有时通过这个错误 (java.lang.RuntimeException:Canvas:试图绘制太大(161907360bytes)位图。android picasso) 我不知道这只是图像加载问题还是试图实现互联网连接另一个问题是它没有不会告诉你它没有连接到互联网,除非我先尝试连接到互联网,然后断开连接后它告诉我没有互联网,我想在启动后立即检查这是 MainActivity 代码
package com.example.hema.presentation
import android.content.Intent
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.hema.databinding.ActivityMainBinding
import com.example.hema.domain.model.News
import com.example.hema.presentation.viewmodel.NewsViewModel
import com.example.hema.util.InternetConnection
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity(),RecyclerAdapter.MyViewHolder.OnClickListener {
@Inject
lateinit var connectivityManager: com.example.hema.util.ConnectivityManager
private lateinit var internetConnection: InternetConnection
lateinit var viewModel: NewsViewModel
lateinit var recyclerView: RecyclerView
lateinit var recyclerAdapter: RecyclerAdapter
private lateinit var binding: ActivityMainBinding
override fun onStart() {
super.onStart()
connectivityManager.registerConnectionObserver(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
recyclerView = binding.recyclerView
recyclerAdapter = RecyclerAdapter(this,this)
recyclerView.adapter = recyclerAdapter
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(this)
viewModel = ViewModelProvider(this).get(NewsViewModel::class.java)
internetConnection= InternetConnection(this)
internetConnection.observe(this, { isNetworkAvailable ->
if (isNetworkAvailable) {
viewModel.getNews()
viewModel.newsList.observe(this, {
recyclerAdapter.setList(it as MutableList<News>)
})
} else {
Toast.makeText(this, "no internet facka", Toast.LENGTH_SHORT).show()
Log.d("TAG", "onCreate: no inetrnet ")
}
})
}
override fun onDestroy() {
viewModel.onDestroy()
connectivityManager.unregisterConnectionObserver(this)
super.onDestroy()
}
override fun onItemClicked(news: News) {
val intent = Intent(this, DetailsActivity::class.java)
intent.putExtra("news",news)
startActivity(intent)
}
}
和 internetConnection 类代码
package com.example.hema.util
import android.content.Context
import android.content.Context.CONNECTIVITY_SERVICE
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkRequest
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.lifecycle.LiveData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
val TAG = "C-Manager"
/**
* Save all available networks with an internet connection to a set (@validNetworks).
* As long as the size of the set > 0, this LiveData emits true.
* MinSdk = 21.
*
* Inspired by:
* https://github.com/AlexSheva-mason/Rick-Morty-Database/blob/master/app/src/main/java/com/shevaalex/android/rickmortydatabase/utils/networking/ConnectionLiveData.kt
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class InternetConnection(context: Context) : LiveData<Boolean>() {
private lateinit var networkCallback: ConnectivityManager.NetworkCallback
private val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
private val validNetworks: MutableSet<Network> = HashSet()
private fun checkValidNetworks() {
postValue(validNetworks.size > 0)
}
override fun onActive() {
networkCallback = createNetworkCallback()
val networkRequest = NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_INTERNET)
.build()
cm.registerNetworkCallback(networkRequest, networkCallback)
}
override fun onInactive() {
cm.unregisterNetworkCallback(networkCallback)
}
private fun createNetworkCallback() = object : ConnectivityManager.NetworkCallback() {
/*
Called when a network is detected. If that network has internet, save it in the Set.
Source: https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback#onAvailable(android.net.Network)
*/
override fun onAvailable(network: Network) {
Log.d(TAG, "onAvailable: ${network}")
val networkCapabilities = cm.getNetworkCapabilities(network)
val hasInternetCapability = networkCapabilities?.hasCapability(NET_CAPABILITY_INTERNET)
Log.d(TAG, "onAvailable: ${network}, $hasInternetCapability")
if (hasInternetCapability == true) {
// check if this network actually has internet
CoroutineScope(Dispatchers.IO).launch {
val hasInternet = DoesNetworkHaveInternet.execute(network.socketFactory)
if(hasInternet){
withContext(Dispatchers.Main){
Log.d(TAG, "onAvailable: adding network. ${network}")
validNetworks.add(network)
checkValidNetworks()
}
}
}
}
}
/*
If the callback was registered with registerNetworkCallback() it will be called for each network which no longer satisfies the criteria of the callback.
Source: https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback#onLost(android.net.Network)
*/
override fun onLost(network: Network) {
Log.d(TAG, "onLost: ${network}")
validNetworks.remove(network)
checkValidNetworks()
}
}
}
和 ConnectivityManager 代码
package com.example.hema.util
import android.app.Application
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.LifecycleOwner
import javax.inject.Inject
import javax.inject.Singleton
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@Singleton
class ConnectivityManager
@Inject
constructor(
application: Application,
) {
private val connectionLiveData = InternetConnection(application)
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun registerConnectionObserver(lifecycleOwner: LifecycleOwner){
connectionLiveData.observe(lifecycleOwner, { isConnected ->
})
}
fun unregisterConnectionObserver(lifecycleOwner: LifecycleOwner){
connectionLiveData.removeObservers(lifecycleOwner)
}
}
还有DoesNetworkHaveInternet
package com.example.hema.util
import android.util.Log
import java.io.IOException
import java.net.InetSocketAddress
import javax.net.SocketFactory
object DoesNetworkHaveInternet {
// Make sure to execute this on a background thread.
fun execute(socketFactory: SocketFactory): Boolean {
return try{
Log.d(TAG, "PINGING google.")
val socket = socketFactory.createSocket() ?: throw IOException("Socket is null.")
socket.connect(InetSocketAddress("8.8.8.8", 53), 1500)
socket.close()
Log.d(TAG, "PING success.")
true
}catch (e: IOException){
Log.e(TAG, "No internet connection. ${e}")
false
}
}
}
最后是 Github Hema上的项目
解决方案
推荐阅读
- sapui5 - 如何使用自定义文件名将数据从 UI5 导出到 Excel
- c# - 如何使用 C# 在 ASP.NET Core Web API 中处理传入的 pdf?
- c# - LINQ 按嵌套在 3 个列表中的属性过滤
- android - Android Chrome 中的 AudioContext 音频口吃
- javascript - javascript代码中的Ajax加载页面不起作用
- ios - 如何在 MVC 中构建模型 - swift
- node.js - Ubuntu上的node_modules(或npm)有什么问题
- javascript - 为什么这个点击事件处理程序没有执行我的代码?
- javascript - 使用带有谓词对象数组的 lodash 过滤器删除结果数据中的属性的更好方法是什么?
- javascript - 如何将对象数组添加到 HTML 表中?