diff --git a/build.gradle b/build.gradle index d25e8283..c213a27a 100644 --- a/build.gradle +++ b/build.gradle @@ -3,31 +3,33 @@ apply plugin: "com.github.ben-manes.versions" buildscript { ext.versions = [ - 'libVersionCode' : 31000, - 'libVersionName' : '3.1.1', - 'compileSdk' : 29, - 'minSdk' : 14, - 'targetSdk' : 29, - 'buildTools' : '29.0.0', - 'okhttp' : '3.12.0', - 'coroutines' : '1.3.9', - 'kotlin' : '1.4.10', - 'appCompat' : '1.1.0', - 'constraintLayout' : '1.1.3', - 'material' : '1.1.0', - 'androidx' : '1.0.0', - 'lifecycle' : '2.2.0', - 'picasso' : '2.71828', - 'junit' : '4.13', - 'extJunit' : '1.1.0', - 'espresso' : '3.1.1', - 'mockito' : '2.23.0', - 'room' : '2.2.5', - 'swipe' : '1.0.0', - 'activityAndroidx' : '1.1.0', - 'androidXTest' : '1.0.0', - 'mockitoKotlin' : '2.2.0', - 'mockitoInline' : '2.27.0' + 'libVersionCode' : 31002, + 'libVersionName' : '3.1.2', + 'compileSdk' : 29, + 'minSdk' : 14, + 'targetSdk' : 29, + 'buildTools' : '30.0.3', + 'okhttp' : '3.12.0', // LTS version, update until December 31, 2021. + 'coroutines' : '1.4.1', + 'testCoroutines' : '1.4.2', + 'kotlin' : '1.4.21', + 'appCompat' : '1.2.0', + 'constraintLayout': '2.0.4', + 'material' : '1.2.1', + 'androidx' : '1.0.0', + 'lifecycle' : '2.2.0', + 'picasso' : '2.71828', + 'junit' : '4.13.1', + 'extJunit' : '1.1.0', + 'espresso' : '3.1.1', + 'mockito' : '2.23.0', + 'room' : '2.2.5', + 'swipe' : '1.1.0', + 'activityAndroidx': '1.1.0', + 'androidXTest' : '1.3.0', + 'mockitoKotlin' : '2.2.0', + 'mockitoInline' : '2.27.0', + 'mockitoCore' : '3.3.3' ] repositories { @@ -37,11 +39,11 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' + classpath 'com.android.tools.build:gradle:4.1.1' + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath "org.jetbrains.kotlin:kotlin-android-extensions:${versions.kotlin}" - classpath "com.github.ben-manes:gradle-versions-plugin:0.28.0" + classpath "com.github.ben-manes:gradle-versions-plugin:0.36.0" } } diff --git a/gradle.properties b/gradle.properties index 8551deef..4cd40bad 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,3 @@ # org.gradle.parallel=true android.enableJetifier=false android.useAndroidX=true -android.enableUnitTestBinaryResources=true diff --git a/rssparser/build.gradle b/rssparser/build.gradle index 76c050f5..998991ce 100644 --- a/rssparser/build.gradle +++ b/rssparser/build.gradle @@ -12,6 +12,7 @@ android { targetSdkVersion versions.targetSdk versionCode versions.libVersionCode versionName versions.libVersionName + buildConfigField 'int', 'VERSION_CODE', String.valueOf(versions.libVersionCode) } buildTypes { @@ -30,7 +31,7 @@ android { } dependencies { - implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}" + api "com.squareup.okhttp3:okhttp:${versions.okhttp}" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutines}" @@ -45,13 +46,10 @@ dependencies { testImplementation "androidx.room:room-testing:${versions.room}" testImplementation "androidx.arch.core:core-testing:2.1.0" testImplementation "androidx.test:core:${versions.androidXTest}" - testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.coroutines}" + testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.testCoroutines}" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:${versions.mockitoKotlin}" - testImplementation "org.mockito:mockito-core:${versions.mockito}" + testImplementation "org.mockito:mockito-core:${versions.mockitoCore}" testImplementation "org.mockito:mockito-inline:${versions.mockitoInline}" - - - } diff --git a/rssparser/publish.gradle b/rssparser/publish.gradle index f4737336..ae75bb54 100644 --- a/rssparser/publish.gradle +++ b/rssparser/publish.gradle @@ -12,9 +12,12 @@ project.ext { mavSiteUrl = 'https://github.com/prof18/RSS-Parser' } +def properties = new Properties() +//properties.load(new FileInputStream("local.properties")) + bintray { - user = System.getenv("bintrayUser") - key = System.getenv("bintrayApiKey") + user = System.getenv("bintrayUser") ?: properties.getProperty("bintray.user") + key = System.getenv("bintrayApiKey") ?: properties.getProperty("bintray.apikey") publications = ['mavenPublish'] configurations = ['archives'] override = true diff --git a/rssparser/src/main/java/com/prof/rssparser/Parser.kt b/rssparser/src/main/java/com/prof/rssparser/Parser.kt index 3f58bc0c..1eaa7621 100644 --- a/rssparser/src/main/java/com/prof/rssparser/Parser.kt +++ b/rssparser/src/main/java/com/prof/rssparser/Parser.kt @@ -178,7 +178,7 @@ class Parser private constructor(private var okHttpClient: OkHttpClient? = null, val cachedFeed = cacheManager?.getCachedFeed(url) if (cachedFeed != null) { Log.d(TAG, "Returning object from cache") - return@withContext cachedFeed as Channel + return@withContext cachedFeed } else { Log.d(TAG, "Returning data from network") val xml = CoroutineEngine.fetchXML(url, okHttpClient, charset) diff --git a/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt b/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt index b6955103..7337e58e 100644 --- a/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt +++ b/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt @@ -255,7 +255,7 @@ internal object CoreXMLParser { if (matcherImg.find()) { val imgTag = matcherImg.group(1) val patternLink = Pattern.compile("src\\s*=\\s*\"(.+?)\"") - val matcherLink = patternLink.matcher(imgTag) + val matcherLink = patternLink.matcher(imgTag ?: "") if (matcherLink.find()) { url = matcherLink.group(1)?.trim() } diff --git a/samplekotlin/build.gradle b/samplekotlin/build.gradle index 2128b6af..c9593dd9 100644 --- a/samplekotlin/build.gradle +++ b/samplekotlin/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' android { compileSdkVersion versions.compileSdk @@ -48,11 +47,10 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutines}" // Architecture components - implementation "androidx.lifecycle:lifecycle-runtime:${versions.lifecycle}" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:${versions.lifecycle}" implementation "androidx.lifecycle:lifecycle-extensions:${versions.lifecycle}" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${versions.lifecycle}" implementation "androidx.activity:activity-ktx:${versions.activityAndroidx}" - implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" } diff --git a/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/ArticleAdapter.kt b/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/ArticleAdapter.kt index a2f5d8aa..061d3aa2 100644 --- a/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/ArticleAdapter.kt +++ b/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/ArticleAdapter.kt @@ -24,11 +24,11 @@ import android.view.View import android.view.ViewGroup import android.webkit.WebChromeClient import android.webkit.WebView +import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.prof.rssparser.Article import com.squareup.picasso.Picasso -import kotlinx.android.synthetic.main.row.view.* import java.text.SimpleDateFormat import java.util.* @@ -40,6 +40,12 @@ class ArticleAdapter(val articles: MutableList
) : RecyclerView.Adapter< override fun onBindViewHolder(holder: ArticleAdapter.ViewHolder, position: Int) = holder.bind(articles[position]) inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + private val title = itemView.findViewById(R.id.title) + private val pubDate = itemView.findViewById(R.id.pubDate) + private val categoriesText = itemView.findViewById(R.id.categories) + private val image = itemView.findViewById(R.id.image) + @SuppressLint("SetJavaScriptEnabled") fun bind(article: Article) { @@ -59,14 +65,14 @@ class ArticleAdapter(val articles: MutableList
) : RecyclerView.Adapter< e.printStackTrace() } - itemView.title.text = article.title + title.text = article.title Picasso.get() .load(article.image) .placeholder(R.drawable.placeholder) - .into(itemView.image) + .into(image) - itemView.pubDate.text = pubDateString + pubDate.text = pubDateString var categories = "" for (i in 0 until article.categories.size) { @@ -77,7 +83,7 @@ class ArticleAdapter(val articles: MutableList
) : RecyclerView.Adapter< } } - itemView.categories.text = categories + categoriesText.text = categories itemView.setOnClickListener { //show article content inside a dialog diff --git a/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/MainActivity.kt b/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/MainActivity.kt index d3a2e15c..9e022f90 100644 --- a/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/MainActivity.kt +++ b/samplekotlin/src/main/java/com/prof/rssparser/sample/kotlin/MainActivity.kt @@ -28,21 +28,21 @@ import android.text.method.LinkMovementMethod import android.view.Menu import android.view.MenuItem import android.view.View +import android.widget.ProgressBar +import android.widget.RelativeLayout import android.widget.TextView import androidx.activity.viewModels import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar import androidx.lifecycle.Observer import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.google.android.material.snackbar.Snackbar import com.prof.rssparser.Parser import com.prof.rssparser.sample.kotlin.util.AlertDialogHelper -import kotlinx.android.synthetic.main.activity_main.toolbar -import kotlinx.android.synthetic.main.content_main.progressBar -import kotlinx.android.synthetic.main.content_main.recycler_view -import kotlinx.android.synthetic.main.content_main.root_layout -import kotlinx.android.synthetic.main.content_main.swipe_layout class MainActivity : AppCompatActivity() { @@ -55,6 +55,12 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + val toolbar = findViewById(R.id.toolbar) + val recyclerView = findViewById(R.id.recycler_view) + val progressBar = findViewById(R.id.progressBar) + val swipeLayout = findViewById(R.id.swipe_layout) + val rootLayout = findViewById(R.id.root_layout) + setSupportActionBar(toolbar) parser = Parser.Builder() @@ -64,37 +70,37 @@ class MainActivity : AppCompatActivity() { .cacheExpirationMillis(24L * 60L * 60L * 100L) // one day .build() - recycler_view.layoutManager = LinearLayoutManager(this) - recycler_view.itemAnimator = DefaultItemAnimator() - recycler_view.setHasFixedSize(true) + recyclerView.layoutManager = LinearLayoutManager(this) + recyclerView.itemAnimator = DefaultItemAnimator() + recyclerView.setHasFixedSize(true) - viewModel.rssChannel.observe(this, Observer { channel -> + viewModel.rssChannel.observe(this, { channel -> if (channel != null) { if (channel.title != null) { title = channel.title } adapter = ArticleAdapter(channel.articles) - recycler_view.adapter = adapter + recyclerView.adapter = adapter adapter.notifyDataSetChanged() progressBar.visibility = View.GONE - swipe_layout.isRefreshing = false + swipeLayout.isRefreshing = false } }) - viewModel.snackbar.observe(this, Observer { value -> + viewModel.snackbar.observe(this, { value -> value?.let { - Snackbar.make(root_layout, value, Snackbar.LENGTH_LONG).show() + Snackbar.make(rootLayout, value, Snackbar.LENGTH_LONG).show() viewModel.onSnackbarShowed() } }) - swipe_layout.setColorSchemeResources(R.color.colorPrimary, R.color.colorPrimaryDark) - swipe_layout.canChildScrollUp() - swipe_layout.setOnRefreshListener { + swipeLayout.setColorSchemeResources(R.color.colorPrimary, R.color.colorPrimaryDark) + swipeLayout.canChildScrollUp() + swipeLayout.setOnRefreshListener { adapter.articles.clear() adapter.notifyDataSetChanged() - swipe_layout.isRefreshing = true + swipeLayout.isRefreshing = true viewModel.fetchFeed(parser) } @@ -104,7 +110,7 @@ class MainActivity : AppCompatActivity() { .setTitle(R.string.alert_title) .setCancelable(false) .setPositiveButton(R.string.alert_positive - ) { dialog, id -> finish() } + ) { _, _ -> finish() } val alert = builder.create() alert.show() @@ -129,7 +135,7 @@ class MainActivity : AppCompatActivity() { " GitHub." + this@MainActivity.getString(R.string.author))) alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK" - ) { dialog, which -> dialog.dismiss() } + ) { dialog, _ -> dialog.dismiss() } alertDialog.show() (alertDialog.findViewById(android.R.id.message) as TextView).movementMethod = LinkMovementMethod.getInstance()