Skip to content

Commit b503bab

Browse files
committed
connectivity check
1 parent 6dab535 commit b503bab

File tree

8 files changed

+90
-12
lines changed

8 files changed

+90
-12
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
package="com.sijanneupane.mvvmnews">
44

55
<uses-permission android:name="android.permission.INTERNET"/>
6+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
67

78
<application
9+
android:name=".NewsApplication"
810
android:allowBackup="true"
911
android:icon="@mipmap/ic_launcher"
1012
android:label="@string/app_name"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.sijanneupane.mvvmnews
2+
3+
import android.app.Application
4+
5+
class NewsApplication : Application()

app/src/main/java/com/sijanneupane/mvvmnews/ui/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class MainActivity : AppCompatActivity() {
2020

2121
//initializations and assign
2222
val repository= NewsRepository(ArticleDatabase(this))
23-
val viewModelProviderFactory= NewsViewModelProviderFactory(repository)
23+
val viewModelProviderFactory= NewsViewModelProviderFactory(application, repository)
2424
viewModel= ViewModelProvider(this, viewModelProviderFactory).get(NewsViewModel::class.java)
2525
val navHostFragment= supportFragmentManager.findFragmentById(R.id.newsNavHostFrag) as NavHostFragment
2626
val navController= navHostFragment.navController

app/src/main/java/com/sijanneupane/mvvmnews/ui/NewsViewModel.kt

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
package com.sijanneupane.mvvmnews.ui
22

3+
import android.app.Application
4+
import android.content.Context
5+
import android.net.ConnectivityManager
6+
import android.net.NetworkCapabilities.*
7+
import androidx.lifecycle.AndroidViewModel
38
import androidx.lifecycle.MutableLiveData
49
import androidx.lifecycle.ViewModel
510
import androidx.lifecycle.viewModelScope
11+
import com.sijanneupane.mvvmnews.NewsApplication
612
import com.sijanneupane.mvvmnews.models.Article
713
import com.sijanneupane.mvvmnews.models.NewsResponse
814
import com.sijanneupane.mvvmnews.repository.NewsRepository
915
import com.sijanneupane.mvvmnews.utils.Resource
1016
import kotlinx.coroutines.launch
1117
import retrofit2.Response
18+
import java.io.IOException
1219

1320
class NewsViewModel(
21+
app: Application,
1422
val newsRepository: NewsRepository //parameter
15-
) : ViewModel(){
23+
) : AndroidViewModel(app){ //inheriting from android view model to use application context
24+
//here we use application context to get the context throughout the app running,
25+
//so it will work even if the activity changes or destroys, the app context will still work until the app's running
1626

1727
//LIVEDATA OBJECT
1828
val breakingNews: MutableLiveData<Resource<NewsResponse>> = MutableLiveData()
@@ -34,24 +44,25 @@ class NewsViewModel(
3444
viewModelScope makes the function alive only as long as the ViewModel is alive
3545
*/
3646
fun getBreakingNews(countryCode: String)= viewModelScope.launch {
37-
breakingNews.postValue(Resource.Loading()) //init loading state before the network call
38-
47+
//breakingNews.postValue(Resource.Loading()) //init loading state before the network call
48+
safeBreakingNewsCall(countryCode)
3949
//actual response
40-
val response= newsRepository.getBreakingNews(countryCode, breakingNewsPage)
50+
//val response= newsRepository.getBreakingNews(countryCode, breakingNewsPage)
4151

4252
//handling response
43-
breakingNews.postValue(handleBreakingNewsResponse(response))
53+
//breakingNews.postValue(handleBreakingNewsResponse(response))
4454
}
4555

4656

4757
fun searchNews(searchQuery: String)= viewModelScope.launch {
48-
searchNews.postValue(Resource.Loading()) //init loading state before the network call
58+
safeSearchNewsCall(searchQuery)
59+
//searchNews.postValue(Resource.Loading()) //init loading state before the network call
4960

5061
//actual response
51-
val response= newsRepository.searchNews(searchQuery, searchNewsPage)
62+
//val response= newsRepository.searchNews(searchQuery, searchNewsPage)
5263

5364
//handling response
54-
searchNews.postValue(handleSearchNewsResponse(response))
65+
//searchNews.postValue(handleSearchNewsResponse(response))
5566
}
5667

5768

@@ -108,4 +119,58 @@ class NewsViewModel(
108119
newsRepository.deleteArticle(article)
109120
}
110121

122+
private suspend fun safeBreakingNewsCall(countryCode: String){
123+
breakingNews.postValue(Resource.Loading())
124+
try{
125+
if (hasInternetConnection()){
126+
val response= newsRepository.getBreakingNews(countryCode, breakingNewsPage)
127+
//handling response
128+
breakingNews.postValue(handleBreakingNewsResponse(response))
129+
}else{
130+
breakingNews.postValue(Resource.Error("No Internet Connection"))
131+
}
132+
133+
} catch (t: Throwable){
134+
when(t){
135+
is IOException-> breakingNews.postValue(Resource.Error("Network Failure"))
136+
else-> breakingNews.postValue(Resource.Error("Conversion Error"))
137+
}
138+
}
139+
}
140+
141+
private suspend fun safeSearchNewsCall(searchQuery: String){
142+
searchNews.postValue(Resource.Loading())
143+
try{
144+
if (hasInternetConnection()){
145+
val response= newsRepository.searchNews(searchQuery, searchNewsPage)
146+
//handling response
147+
searchNews.postValue(handleSearchNewsResponse(response))
148+
}else{
149+
searchNews.postValue(Resource.Error("No Internet Connection"))
150+
}
151+
152+
} catch (t: Throwable){
153+
when(t){
154+
is IOException-> searchNews.postValue(Resource.Error("Network Failure"))
155+
else-> searchNews.postValue(Resource.Error("Conversion Error"))
156+
}
157+
}
158+
}
159+
160+
161+
private fun hasInternetConnection(): Boolean{
162+
val connectivityManager= getApplication<NewsApplication>().getSystemService(
163+
Context.CONNECTIVITY_SERVICE
164+
) as ConnectivityManager
165+
166+
val activeNetwork= connectivityManager.activeNetwork?: return false
167+
val capabilities= connectivityManager.getNetworkCapabilities(activeNetwork)?: return false
168+
169+
return when{
170+
capabilities.hasTransport(TRANSPORT_WIFI)-> true
171+
capabilities.hasTransport(TRANSPORT_CELLULAR)-> true
172+
capabilities.hasTransport(TRANSPORT_ETHERNET)->true
173+
else -> false
174+
}
175+
}
111176
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package com.sijanneupane.mvvmnews.ui
22

3+
import android.app.Application
34
import androidx.lifecycle.ViewModel
45
import androidx.lifecycle.ViewModelProvider
56
import com.sijanneupane.mvvmnews.repository.NewsRepository
67
/*
78
To define how our view model should be created
89
*/
910
class NewsViewModelProviderFactory(
11+
val app: Application,
1012
val newsRepository: NewsRepository
1113
) : ViewModelProvider.Factory{
1214

1315
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
14-
return NewsViewModel(newsRepository) as T
16+
return NewsViewModel(app, newsRepository) as T
1517
}
1618
}

app/src/main/java/com/sijanneupane/mvvmnews/ui/fragments/ArticleFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ArticleFragment : Fragment(R.layout.fragment_article){
2424
val article = args.article
2525
webView.apply {
2626
webViewClient= WebViewClient()
27-
loadUrl(article.url)
27+
loadUrl(article.url.toString())
2828
}
2929

3030
//save article

app/src/main/java/com/sijanneupane/mvvmnews/ui/fragments/BreakingNewsFragment.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.util.Log
55
import android.view.View
66
import android.widget.AbsListView
77
import android.widget.LinearLayout
8+
import android.widget.Toast
89
import androidx.fragment.app.Fragment
910
import androidx.lifecycle.Observer
1011
import androidx.lifecycle.viewModelScope
@@ -64,6 +65,7 @@ class BreakingNewsFragment : Fragment(R.layout.fragment_breaking_news) {
6465
hideProgressBar()
6566
response.message?.let { message->
6667
Log.e(TAG, "An error occured: $message" )
68+
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG).show()
6769
}
6870
}
6971
is Resource.Loading->{

app/src/main/java/com/sijanneupane/mvvmnews/ui/fragments/SearchNewsFragment.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.os.Bundle
44
import android.util.Log
55
import android.view.View
66
import android.widget.AbsListView
7+
import android.widget.Toast
78
import androidx.core.widget.addTextChangedListener
89
import androidx.fragment.app.Fragment
910
import androidx.lifecycle.Observer
@@ -82,7 +83,8 @@ class SearchNewsFragment : Fragment (R.layout.fragment_search_news) {
8283
is Resource.Error->{
8384
hideProgressBar()
8485
response.message?.let { message->
85-
Log.e(TAG, "An error occured: $message" )
86+
Log.e(TAG, "An error occurred: $message" )
87+
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG).show()
8688
}
8789
}
8890
is Resource.Loading->{

0 commit comments

Comments
 (0)