首页 > 解决方案 > 我正在尝试检查互联网连接,但我的代码可能有问题,我无法弄清楚?

问题描述

所以我在这个简单的 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上的项目

标签: androidkotlinandroid-livedatainternet-connection

解决方案


推荐阅读