Browse Source

added RSS parser and simple news reader. Clicking on title opens website

yattoz 4 years ago
parent
commit
99961e8a4e

+ 4 - 1
app/build.gradle View File

69
     implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
69
     implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
70
     implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
70
     implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
71
 
71
 
72
-    implementation 'androidx.recyclerview:recyclerview:1.0.0'
72
+    implementation 'androidx.recyclerview:recyclerview:1.1.0'
73
     implementation 'androidx.preference:preference:1.1.0'
73
     implementation 'androidx.preference:preference:1.1.0'
74
 
74
 
75
     // jsoup HTML parser library @ https://jsoup.org/
75
     // jsoup HTML parser library @ https://jsoup.org/
76
     // implementation 'org.jsoup:jsoup:1.12.1'
76
     // implementation 'org.jsoup:jsoup:1.12.1'
77
 
77
 
78
+    // RSS parser library @ https://github.com/prof18/RSS-Parser
79
+    implementation 'com.prof.rssparser:rssparser:2.0.4'
80
+
78
     def work_version = "2.2.0"
81
     def work_version = "2.2.0"
79
     implementation "androidx.work:work-runtime-ktx:$work_version"
82
     implementation "androidx.work:work-runtime-ktx:$work_version"
80
 
83
 

+ 1 - 0
app/src/main/java/fr/forum_thalie/tsumugi/ui/news/News.kt View File

7
     var text: String = ""
7
     var text: String = ""
8
     var header: String = ""
8
     var header: String = ""
9
     var author: String = ""
9
     var author: String = ""
10
+    var link: String = ""
10
     var date: Date = Date()
11
     var date: Date = Date()
11
 
12
 
12
     override fun toString() : String
13
     override fun toString() : String

+ 10 - 1
app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsAdapter.kt View File

1
 package fr.forum_thalie.tsumugi.ui.news
1
 package fr.forum_thalie.tsumugi.ui.news
2
 
2
 
3
 import android.annotation.SuppressLint
3
 import android.annotation.SuppressLint
4
+import android.content.Context
5
+import android.content.Intent
6
+import android.net.Uri
4
 import android.widget.TextView
7
 import android.widget.TextView
5
 import android.view.LayoutInflater
8
 import android.view.LayoutInflater
6
 import android.view.ViewGroup
9
 import android.view.ViewGroup
7
 import androidx.constraintlayout.widget.ConstraintLayout
10
 import androidx.constraintlayout.widget.ConstraintLayout
11
+import androidx.core.content.ContextCompat.startActivity
8
 import androidx.core.text.HtmlCompat
12
 import androidx.core.text.HtmlCompat
9
 import androidx.core.widget.TextViewCompat
13
 import androidx.core.widget.TextViewCompat
10
 import androidx.recyclerview.widget.RecyclerView
14
 import androidx.recyclerview.widget.RecyclerView
11
 import fr.forum_thalie.tsumugi.R
15
 import fr.forum_thalie.tsumugi.R
12
 import kotlin.collections.ArrayList
16
 import kotlin.collections.ArrayList
13
 
17
 
14
-class NewsAdapter(private val dataSet: ArrayList<News>
18
+class NewsAdapter(private val dataSet: ArrayList<News>, private val c: Context
15
     /*,
19
     /*,
16
     context: Context,
20
     context: Context,
17
     resource: Int,
21
     resource: Int,
45
         val author = holder.itemView.findViewById<TextView>(R.id.news_author)
49
         val author = holder.itemView.findViewById<TextView>(R.id.news_author)
46
         val header = holder.itemView.findViewById<TextView>(R.id.news_header)
50
         val header = holder.itemView.findViewById<TextView>(R.id.news_header)
47
         title.text = dataSet[position].title
51
         title.text = dataSet[position].title
52
+        title.setOnClickListener {
53
+            val i = Intent(Intent.ACTION_VIEW)
54
+            i.data = Uri.parse(dataSet[position].link)
55
+            c.startActivity(i)
56
+        }
48
         text.text = HtmlCompat.fromHtml(dataSet[position].text, HtmlCompat.FROM_HTML_MODE_LEGACY)
57
         text.text = HtmlCompat.fromHtml(dataSet[position].text, HtmlCompat.FROM_HTML_MODE_LEGACY)
49
         header.text = HtmlCompat.fromHtml(dataSet[position].header, HtmlCompat.FROM_HTML_MODE_LEGACY).replace(Regex("\n"), " ")
58
         header.text = HtmlCompat.fromHtml(dataSet[position].header, HtmlCompat.FROM_HTML_MODE_LEGACY).replace(Regex("\n"), " ")
50
         author.text = "| ${dataSet[position].author}"
59
         author.text = "| ${dataSet[position].author}"

+ 1 - 1
app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsFragment.kt View File

29
         val root = inflater.inflate(R.layout.fragment_news, container, false) as androidx.swiperefreshlayout.widget.SwipeRefreshLayout
29
         val root = inflater.inflate(R.layout.fragment_news, container, false) as androidx.swiperefreshlayout.widget.SwipeRefreshLayout
30
 
30
 
31
         viewManager = LinearLayoutManager(context)
31
         viewManager = LinearLayoutManager(context)
32
-        viewAdapter = NewsAdapter(newsViewModel.newsArray)
32
+        viewAdapter = NewsAdapter(newsViewModel.newsArray, context!!)
33
         recyclerView = root.findViewById<RecyclerView>(R.id.news_recycler).apply {
33
         recyclerView = root.findViewById<RecyclerView>(R.id.news_recycler).apply {
34
             // use this setting to improve performance if you know that changes
34
             // use this setting to improve performance if you know that changes
35
             // in content do not change the layout size of the RecyclerView
35
             // in content do not change the layout size of the RecyclerView

+ 42 - 5
app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsViewModel.kt View File

3
 import android.util.Log
3
 import android.util.Log
4
 import androidx.lifecycle.ViewModel
4
 import androidx.lifecycle.ViewModel
5
 import androidx.recyclerview.widget.RecyclerView
5
 import androidx.recyclerview.widget.RecyclerView
6
+import com.prof.rssparser.Parser
6
 import fr.forum_thalie.tsumugi.Async
7
 import fr.forum_thalie.tsumugi.Async
7
 import fr.forum_thalie.tsumugi.tag
8
 import fr.forum_thalie.tsumugi.tag
9
+import kotlinx.coroutines.CoroutineScope
10
+import kotlinx.coroutines.Dispatchers
11
+import kotlinx.coroutines.Job
12
+import kotlinx.coroutines.launch
8
 import org.json.JSONArray
13
 import org.json.JSONArray
9
 import org.json.JSONObject
14
 import org.json.JSONObject
10
 import java.net.URL
15
 import java.net.URL
11
 import java.text.SimpleDateFormat
16
 import java.text.SimpleDateFormat
12
 import java.util.*
17
 import java.util.*
13
 import kotlin.collections.ArrayList
18
 import kotlin.collections.ArrayList
19
+import kotlin.math.max
20
+import kotlin.math.min
14
 
21
 
15
 
22
 
16
 class NewsViewModel : ViewModel() {
23
 class NewsViewModel : ViewModel() {
17
 
24
 
18
     val newsArray : ArrayList<News> = ArrayList()
25
     val newsArray : ArrayList<News> = ArrayList()
19
 
26
 
20
-    private val urlToScrape = "https://r-a-d.io/api/news"
27
+    private val urlToScrape = "https://tsumugi.forum-thalie.fr/?feed=rss2"
21
 
28
 
22
     private val scrape : (Any?) -> Unit =
29
     private val scrape : (Any?) -> Unit =
23
     {
30
     {
41
         }
48
         }
42
     }
49
     }
43
 
50
 
51
+    private val viewModelJob = Job()
52
+    private val coroutineScope = CoroutineScope(Dispatchers.Main + viewModelJob)
53
+
44
     fun fetch(root: androidx.swiperefreshlayout.widget.SwipeRefreshLayout? = null, viewAdapter: RecyclerView.Adapter<*>? = null)
54
     fun fetch(root: androidx.swiperefreshlayout.widget.SwipeRefreshLayout? = null, viewAdapter: RecyclerView.Adapter<*>? = null)
45
     {
55
     {
46
-        val post : (parameter: Any?) -> Unit = {
47
-            root?.isRefreshing = false
48
-            viewAdapter?.notifyDataSetChanged()
56
+        val maxNumberOfArticles = 5
57
+        coroutineScope.launch(Dispatchers.Main) {
58
+            Log.d(tag, "launching coroutine")
59
+            try {
60
+                val parser = Parser()
61
+                val articleList = parser.getArticles(urlToScrape)
62
+                newsArray.clear()
63
+                for (i in 0 until min(articleList.size, maxNumberOfArticles))
64
+                {
65
+                    val item = articleList[i]
66
+                    Log.d(tag, "i = $i / ${articleList.size}")
67
+                    val news = News()
68
+                    news.title = item.title ?: ""
69
+                    news.link = item.link ?: urlToScrape
70
+                    news.author = item.author ?: ""
71
+                    news.text = item.content ?: ""
72
+                    news.header = item.description ?: ""
73
+
74
+                    //val formatter6 = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
75
+
76
+                    //news.date = formatter6.parse(item.pubDate ?: Date().toString()) ?: Date()
77
+
78
+                    Log.d(tag, "$news - ${item.pubDate}")
79
+                    newsArray.add(news)
80
+                }
81
+                // The list contains all article's data. For example you can use it for your adapter.
82
+                root?.isRefreshing = false
83
+                viewAdapter?.notifyDataSetChanged()
84
+            } catch (e: Exception) {
85
+                // Handle the exception
86
+            }
49
         }
87
         }
50
-        Async(scrape, post)
51
     }
88
     }
52
 }
89
 }