From f1392aaaa4f52f3fb1fad2e920cf78106efbf81b Mon Sep 17 00:00:00 2001 From: Norbel Ambanumben Date: Wed, 30 Aug 2023 07:23:01 +0100 Subject: [PATCH 1/5] Replace `HeterogeneousRecyclerAdapter` with `RecyclerView.Adapter` and add a `ViewModel` for state management --- app/build.gradle | 17 ++- .../ooniprobe/adapters/DashboardAdapter.kt | 105 +++++++++++++ .../ooniprobe/fragment/DashboardFragment.java | 140 ------------------ .../ooniprobe/fragment/DashboardFragment.kt | 120 +++++++++++++++ .../fragment/dashboard/DashboardViewModel.kt | 44 ++++++ .../ooniprobe/item/SeperatorItem.java | 1 + .../ooniprobe/item/TestsuiteItem.java | 1 + 7 files changed, 282 insertions(+), 146 deletions(-) create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/adapters/DashboardAdapter.kt delete mode 100644 app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/fragment/dashboard/DashboardViewModel.kt diff --git a/app/build.gradle b/app/build.gradle index ac15c07d7..763959db0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,6 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' apply from: 'jacoco.gradle' android { @@ -94,6 +96,9 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 + } buildFeatures { viewBinding = true } @@ -114,7 +119,7 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' // Third-party - annotationProcessor 'com.github.Raizlabs.DBFlow:dbflow-processor:4.2.4' + kapt 'com.github.Raizlabs.DBFlow:dbflow-processor:4.2.4' implementation 'com.github.Raizlabs.DBFlow:dbflow-core:4.2.4' implementation 'com.github.Raizlabs.DBFlow:dbflow:4.2.4' @@ -124,7 +129,7 @@ dependencies { implementation 'com.jakewharton:butterknife:10.2.3' - annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' + kapt 'com.jakewharton:butterknife-compiler:10.2.3' implementation 'com.github.xanscale.LocalhostToolkit:app:19.05.01' implementation 'com.airbnb.android:lottie:3.0.7' @@ -142,8 +147,8 @@ dependencies { fullImplementation 'com.google.android.play:core:1.10.3' // Dependency Injection - implementation 'com.google.dagger:dagger:2.36' - annotationProcessor 'com.google.dagger:dagger-compiler:2.36' + implementation 'com.google.dagger:dagger:2.45' + kapt 'com.google.dagger:dagger-compiler:2.45' // Logger implementation project(':applogger') @@ -159,7 +164,7 @@ dependencies { testImplementation 'org.robolectric:robolectric:4.5.1' testImplementation 'com.github.blocoio:faker:1.2.8' testImplementation 'org.ooni:oonimkall:2023.07.18-162729' - testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.36' + testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.45' // Instrumentation Testing androidTestImplementation 'tools.fastlane:screengrab:2.0.0' @@ -179,7 +184,7 @@ dependencies { exclude module: 'recyclerview-v7' } androidTestImplementation('com.schibsted.spain:barista:3.9.0') - androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.36" + androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.45" } static def versionCodeDate() { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/adapters/DashboardAdapter.kt b/app/src/main/java/org/openobservatory/ooniprobe/adapters/DashboardAdapter.kt new file mode 100644 index 000000000..26baea9f4 --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/adapters/DashboardAdapter.kt @@ -0,0 +1,105 @@ +package org.openobservatory.ooniprobe.adapters + +import android.content.res.Resources +import android.graphics.PorterDuff +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.cardview.widget.CardView +import androidx.recyclerview.widget.RecyclerView +import org.openobservatory.ooniprobe.R +import org.openobservatory.ooniprobe.common.PreferenceManager +import org.openobservatory.ooniprobe.databinding.ItemSeperatorBinding +import org.openobservatory.ooniprobe.databinding.ItemTestsuiteBinding +import org.openobservatory.ooniprobe.test.suite.AbstractSuite + +class DashboardAdapter( + private val items: List, + private val onClickListener: View.OnClickListener, + private val preferenceManager: PreferenceManager, +) : RecyclerView.Adapter() { + + companion object { + private const val VIEW_TYPE_TITLE = 0 + private const val VIEW_TYPE_CARD = 1 + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + VIEW_TYPE_TITLE -> { + CardGroupTitleViewHolder( + ItemSeperatorBinding.inflate( + LayoutInflater.from(parent.context), parent, false + ) + ) + } + + else -> { + CardViewHolder( + ItemTestsuiteBinding.inflate( + LayoutInflater.from(parent.context), parent, false + ) + ) + } + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + val item = items[position] + when (holder.itemViewType) { + VIEW_TYPE_TITLE -> { + } + + VIEW_TYPE_CARD -> { + val cardHolder = holder as CardViewHolder + if (item is AbstractSuite) { + cardHolder.binding.apply { + title.setText(item.title) + desc.setText(item.cardDesc) + icon.setImageResource(item.iconGradient) + } + holder.itemView.tag = item + if (item.isTestEmpty(preferenceManager)) { + holder.setIsRecyclable(false) + holder.itemView.apply { + elevation = 0f + isClickable = false + } + val resources: Resources = holder.itemView.context.resources + (holder.itemView as CardView).setCardBackgroundColor(resources.getColor(R.color.disabled_test_background)) + holder.binding.apply { + title.setTextColor(resources.getColor(R.color.disabled_test_text)) + desc.setTextColor(resources.getColor(R.color.disabled_test_text)) + icon.setColorFilter(resources.getColor(R.color.disabled_test_text), PorterDuff.Mode.SRC_IN) + } + } else { + holder.itemView.setOnClickListener(onClickListener) + } + } + } + } + } + + override fun getItemCount(): Int { + return items.size + } + + override fun getItemViewType(position: Int): Int { + return when (items[position]) { + is String -> VIEW_TYPE_TITLE + else -> VIEW_TYPE_CARD + } + } + + /** + * ViewHolder for dashboard item group + * @param binding + */ + class CardGroupTitleViewHolder(var binding: ItemSeperatorBinding) : RecyclerView.ViewHolder(binding.root) + + /** + * ViewHolder for dashboard item + * @param binding + */ + class CardViewHolder(var binding: ItemTestsuiteBinding) : RecyclerView.ViewHolder(binding.root) +} \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java deleted file mode 100644 index 7eee1ca50..000000000 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.openobservatory.ooniprobe.fragment; - -import android.os.Bundle; -import android.text.format.DateUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.ActivityCompat; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; - -import org.openobservatory.ooniprobe.R; -import org.openobservatory.ooniprobe.activity.AbstractActivity; -import org.openobservatory.ooniprobe.activity.OverviewActivity; -import org.openobservatory.ooniprobe.activity.RunningActivity; -import org.openobservatory.ooniprobe.common.Application; -import org.openobservatory.ooniprobe.common.PreferenceManager; -import org.openobservatory.ooniprobe.common.ReachabilityManager; -import org.openobservatory.ooniprobe.common.ThirdPartyServices; -import org.openobservatory.ooniprobe.databinding.FragmentDashboardBinding; -import org.openobservatory.ooniprobe.item.SeperatorItem; -import org.openobservatory.ooniprobe.item.TestsuiteItem; -import org.openobservatory.ooniprobe.model.database.Result; -import org.openobservatory.ooniprobe.test.TestAsyncTask; -import org.openobservatory.ooniprobe.test.suite.AbstractSuite; - -import java.util.ArrayList; - -import javax.inject.Inject; - -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerAdapter; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - -public class DashboardFragment extends Fragment implements View.OnClickListener { - - @Inject - PreferenceManager preferenceManager; - - private ArrayList items; - - private ArrayList testSuites; - - private HeterogeneousRecyclerAdapter adapter; - - private FragmentDashboardBinding binding; - - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { - binding = FragmentDashboardBinding.inflate(inflater,container,false); - ((Application) getActivity().getApplication()).getFragmentComponent().inject(this); - ((AppCompatActivity) getActivity()).setSupportActionBar(binding.toolbar); - ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(null); - items = new ArrayList<>(); - testSuites = new ArrayList<>(); - adapter = new HeterogeneousRecyclerAdapter<>(getActivity(), items); - binding.recycler.setAdapter(adapter); - binding.recycler.setLayoutManager(new LinearLayoutManager(getActivity())); - binding.runAll.setOnClickListener(v1 -> runAll()); - binding.vpn.setOnClickListener(view -> ((Application) getActivity().getApplication()).openVPNSettings()); - return binding.getRoot(); - } - - @Override public void onResume() { - super.onResume(); - items.clear(); - testSuites.clear(); - testSuites.addAll(TestAsyncTask.getSuites()); - - ArrayList emptySuites = new ArrayList<>(); - for (AbstractSuite testSuite : testSuites){ - if(testSuite.getTestList(preferenceManager).length > 0){ - items.add(new TestsuiteItem(testSuite, this, preferenceManager)); - } else { - emptySuites.add(testSuite); - } - } - - if(!emptySuites.isEmpty()){ - items.add(new SeperatorItem()); - - for(AbstractSuite emptyTest: emptySuites) - items.add(new TestsuiteItem(emptyTest, this, preferenceManager)); - } - - - - setLastTest(); - adapter.notifyTypesChanged(); - if (ReachabilityManager.isVPNinUse(this.getContext()) - && preferenceManager.isWarnVPNInUse()) - binding.vpn.setVisibility(View.VISIBLE); - else - binding.vpn.setVisibility(View.GONE); - } - - private void setLastTest() { - Result lastResult = Result.getLastResult(); - if (lastResult == null) - binding.lastTested.setText(getString(R.string.Dashboard_Overview_LatestTest) - + " " + - getString(R.string.Dashboard_Overview_LastRun_Never)); - else - binding.lastTested.setText(getString(R.string.Dashboard_Overview_LatestTest) - + " " + - DateUtils.getRelativeTimeSpanString(lastResult.start_time.getTime())); - } - - public void runAll() { - RunningActivity.runAsForegroundService((AbstractActivity) getActivity(), testSuites, this::onTestServiceStartedListener, preferenceManager); - } - - private void onTestServiceStartedListener() { - try { - ((AbstractActivity) getActivity()).bindTestService(); - } catch (Exception e) { - e.printStackTrace(); - ThirdPartyServices.logException(e); - } - } - - @Override public void onClick(View v) { - AbstractSuite testSuite = (AbstractSuite) v.getTag(); - switch (v.getId()) { - case R.id.run: - RunningActivity.runAsForegroundService( - (AbstractActivity) getActivity(), - testSuite.asArray(), - this::onTestServiceStartedListener, - preferenceManager - ); - break; - default: - ActivityCompat.startActivity(getActivity(), OverviewActivity.newIntent(getActivity(), testSuite), null); - break; - } - } -} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt new file mode 100644 index 000000000..a973b1cee --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt @@ -0,0 +1,120 @@ +package org.openobservatory.ooniprobe.fragment + +import android.os.Bundle +import android.text.format.DateUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import org.openobservatory.ooniprobe.R +import org.openobservatory.ooniprobe.activity.AbstractActivity +import org.openobservatory.ooniprobe.activity.OverviewActivity +import org.openobservatory.ooniprobe.activity.RunningActivity +import org.openobservatory.ooniprobe.adapters.DashboardAdapter +import org.openobservatory.ooniprobe.common.Application +import org.openobservatory.ooniprobe.common.PreferenceManager +import org.openobservatory.ooniprobe.common.ReachabilityManager +import org.openobservatory.ooniprobe.common.ThirdPartyServices +import org.openobservatory.ooniprobe.databinding.FragmentDashboardBinding +import org.openobservatory.ooniprobe.fragment.dashboard.DashboardViewModel +import org.openobservatory.ooniprobe.model.database.Result +import org.openobservatory.ooniprobe.test.suite.AbstractSuite +import javax.inject.Inject + +class DashboardFragment : Fragment(), View.OnClickListener { + @Inject + lateinit var preferenceManager: PreferenceManager + + @Inject + lateinit var viewModel: DashboardViewModel + private var testSuites: ArrayList = ArrayList() + private lateinit var binding: FragmentDashboardBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentDashboardBinding.inflate(inflater, container, false) + (requireActivity().application as Application).fragmentComponent.inject(this) + (requireActivity() as AppCompatActivity).apply { + setSupportActionBar(binding.toolbar) + supportActionBar?.title = null + } + binding.apply { + runAll.setOnClickListener { _: View? -> runAll() } + vpn.setOnClickListener { _: View? -> (requireActivity().application as Application).openVPNSettings() } + } + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + viewModel.getGroupedItemList().observe(viewLifecycleOwner) { items -> + binding.recycler.layoutManager = LinearLayoutManager(requireContext()) + binding.recycler.adapter = DashboardAdapter(items, this, preferenceManager) + } + + viewModel.items.observe(viewLifecycleOwner) { items -> + testSuites.apply { + clear() + addAll(items) + } + } + } + + override fun onResume() { + super.onResume() + setLastTest() + if (ReachabilityManager.isVPNinUse(this.context) + && preferenceManager.isWarnVPNInUse + ) binding.vpn.visibility = View.VISIBLE else binding.vpn.visibility = View.GONE + } + + private fun setLastTest() { + val lastResult = Result.getLastResult() + if (lastResult == null) { + (getString(R.string.Dashboard_Overview_LatestTest) + " " + getString(R.string.Dashboard_Overview_LastRun_Never)) + .also { binding.lastTested.text = it } + } else { + (getString(R.string.Dashboard_Overview_LatestTest) + " " + DateUtils.getRelativeTimeSpanString(lastResult.start_time.time)) + .also { binding.lastTested.text = it } + } + } + + private fun runAll() { + RunningActivity.runAsForegroundService( + activity as AbstractActivity?, + testSuites, + { onTestServiceStartedListener() }, + preferenceManager + ) + } + + private fun onTestServiceStartedListener() = try { + (requireActivity() as AbstractActivity).bindTestService() + } catch (e: Exception) { + e.printStackTrace() + ThirdPartyServices.logException(e) + } + + override fun onClick(v: View) { + val testSuite = v.tag as AbstractSuite + when (v.id) { + R.id.run -> RunningActivity.runAsForegroundService( + activity as AbstractActivity?, + testSuite.asArray(), { onTestServiceStartedListener() }, + preferenceManager + ) + + else -> ActivityCompat.startActivity( + requireActivity(), + OverviewActivity.newIntent(activity, testSuite), + null + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/dashboard/DashboardViewModel.kt b/app/src/main/java/org/openobservatory/ooniprobe/fragment/dashboard/DashboardViewModel.kt new file mode 100644 index 000000000..009a3cab0 --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/dashboard/DashboardViewModel.kt @@ -0,0 +1,44 @@ +package org.openobservatory.ooniprobe.fragment.dashboard + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import org.openobservatory.ooniprobe.common.PreferenceManager +import org.openobservatory.ooniprobe.test.TestAsyncTask +import org.openobservatory.ooniprobe.test.suite.AbstractSuite +import javax.inject.Inject + +class DashboardViewModel @Inject constructor(private val preferenceManager: PreferenceManager) : ViewModel() { + private val enabledTitle: String = "Enabled" + private val groupedItemList = MutableLiveData>() + val items = MutableLiveData>(TestAsyncTask.getSuites()) + + fun getGroupedItemList(): LiveData> { + if (groupedItemList.value == null) { + fetchItemList() + } + return groupedItemList + } + + private fun fetchItemList() { + + val groupedItems = items.value!!.sortedBy { it.getTestList(preferenceManager).isEmpty() } + .groupBy { + return@groupBy if ((it.getTestList(preferenceManager).isNotEmpty())) { + enabledTitle + } else { + "" + } + } + + val groupedItemList = mutableListOf() + groupedItems.forEach { (status, itemList) -> + if (status != enabledTitle){ + groupedItemList.add(status) + } + groupedItemList.addAll(itemList) + } + + this.groupedItemList.value = groupedItemList + } +} \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/SeperatorItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/SeperatorItem.java index 5b50974d5..454be6618 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/SeperatorItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/SeperatorItem.java @@ -11,6 +11,7 @@ import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; +@Deprecated public class SeperatorItem extends HeterogeneousRecyclerItem { public SeperatorItem() { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/TestsuiteItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/TestsuiteItem.java index 9eb8bf60b..a334a751b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/TestsuiteItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/TestsuiteItem.java @@ -13,6 +13,7 @@ import org.openobservatory.ooniprobe.databinding.ItemTestsuiteBinding; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; +@Deprecated public class TestsuiteItem extends HeterogeneousRecyclerItem { private final View.OnClickListener onClickListener; private final PreferenceManager preferenceManager; From 5ac447939a85ae3022bcb4da824e0c1f5cc4b47f Mon Sep 17 00:00:00 2001 From: Norbel Ambanumben Date: Wed, 30 Aug 2023 08:23:03 +0100 Subject: [PATCH 2/5] Update annotation processing for tests --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 763959db0..1204bc5d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -164,7 +164,7 @@ dependencies { testImplementation 'org.robolectric:robolectric:4.5.1' testImplementation 'com.github.blocoio:faker:1.2.8' testImplementation 'org.ooni:oonimkall:2023.07.18-162729' - testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.45' + kaptTest 'com.google.dagger:dagger-compiler:2.45' // Instrumentation Testing androidTestImplementation 'tools.fastlane:screengrab:2.0.0' @@ -184,7 +184,7 @@ dependencies { exclude module: 'recyclerview-v7' } androidTestImplementation('com.schibsted.spain:barista:3.9.0') - androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.45" + kaptAndroidTest "com.google.dagger:dagger-compiler:2.45" } static def versionCodeDate() { From 631230a80f025e19b77398fe5cd05fd5932e9691 Mon Sep 17 00:00:00 2001 From: Norbel Ambanumben Date: Wed, 18 Oct 2023 12:22:24 +0100 Subject: [PATCH 3/5] Updated shared module --- shared-test/build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared-test/build.gradle b/shared-test/build.gradle index 607a28dff..1877880b9 100644 --- a/shared-test/build.gradle +++ b/shared-test/build.gradle @@ -1,5 +1,7 @@ plugins { id 'com.android.library' + id 'kotlin-android' + id 'kotlin-kapt' } android { @@ -9,10 +11,8 @@ android { defaultConfig { minSdk 21 } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 } flavorDimensions = ['testing', 'license'] productFlavors { @@ -41,12 +41,12 @@ dependencies { // Dependency Injection (https://dagger.dev/) implementation libs.google.dagger - annotationProcessor libs.google.dagger.compiler + kapt libs.google.dagger.compiler // Database Library (https://github.com/agrosner/DBFlow) implementation libs.dbflow.core implementation libs.dbflow.lib - annotationProcessor libs.dbflow.processor + kapt libs.dbflow.processor // Gson Serialization Library (https://github.com/google/gson) implementation libs.google.gson From 1f813aff981b6ec20b60864e1dbea9afa5942504 Mon Sep 17 00:00:00 2001 From: Norbel Ambanumben Date: Sat, 21 Oct 2023 17:50:30 +0100 Subject: [PATCH 4/5] AGP upgrade --- .github/workflows/archive.yml | 4 ++-- .github/workflows/build.yml | 2 +- .github/workflows/emulator.yml | 2 +- .github/workflows/test.yml | 2 +- app/build.gradle | 6 +++--- app/jacoco.gradle | 20 +++++++++++++------- gradle.properties | 3 +++ gradle/libs.versions.toml | 6 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- shared-test/build.gradle | 11 ++++++++--- 10 files changed, 36 insertions(+), 22 deletions(-) diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index d41537923..b04392ac3 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: checkout uses: actions/checkout@v2 @@ -16,4 +16,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: dev-apk - path: app/build/outputs/apk/devFull/release \ No newline at end of file + path: app/build/outputs/apk/devFull/release diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6ed6c7a7e..46f49645d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: checkout uses: actions/checkout@v2 diff --git a/.github/workflows/emulator.yml b/.github/workflows/emulator.yml index 0a599c15a..de92c9393 100644 --- a/.github/workflows/emulator.yml +++ b/.github/workflows/emulator.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: checkout uses: actions/checkout@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e678fedd6..f743fca58 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: checkout uses: actions/checkout@v2 diff --git a/app/build.gradle b/app/build.gradle index ade32bc44..1c215b084 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,11 +86,11 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 + jvmTarget = JavaVersion.VERSION_17 } buildFeatures { viewBinding = true diff --git a/app/jacoco.gradle b/app/jacoco.gradle index f75812752..15b2b36c1 100644 --- a/app/jacoco.gradle +++ b/app/jacoco.gradle @@ -48,13 +48,19 @@ task jacocoAndroidTestReport(type: JacocoReport) { executionData.from += fileTree(dir: codeCoverageDataLocation, includes: ['**/*.ec']) } - reports { - html.enabled true - html.destination file("${buildDir}/reports/coverage") - xml.enabled true - xml.destination file("${buildDir}/reports/coverage.xml") - csv.enabled false - } + reports { + html { + enabled true + destination file("${buildDir}/reports/coverage") + } + xml { + enabled true + destination file("${buildDir}/reports/coverage.xml") + } + csv { + enabled false + } + } doLast { println "Wrote HTML coverage report to ${reports.html.destination}/index.html" diff --git a/gradle.properties b/gradle.properties index 8de505811..a8c570082 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,10 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. +android.defaults.buildfeatures.buildconfig=true android.enableJetifier=true +android.nonFinalResIds=false +android.nonTransitiveRClass=false android.useAndroidX=true org.gradle.jvmargs=-Xmx1536m # When configured, Gradle will run in incubating parallel mode. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 45a0cb6c7..4c1c32406 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -androidGradlePlugin = "7.4.1" +androidGradlePlugin = "8.1.2" barista = "3.9.0" countlySdk = "21.11.0" faker = "1.2.8" @@ -10,7 +10,7 @@ fastlaneScreengrab = "2.0.0" sentryAndroid = "6.3.0" xanscaleLocalhostToolkit = "19.05.01" commonsIo = "2.6" -jacoco = "0.8.5" +jacoco = "0.8.7" kotlin = "1.8.0" # Android X @@ -29,7 +29,7 @@ androidxEspressoCore = "3.5.1" googleGson = "2.8.9" googleGuava = "30.1.1-android" googleMaterial = "1.6.1" -googleDagger = "2.44.2" +googleDagger = "2.45" googleFirebaseBon = "26.3.0" googlePlaycore = "1.10.3" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2ec77e51a..3a0290794 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/shared-test/build.gradle b/shared-test/build.gradle index 1877880b9..34d70a978 100644 --- a/shared-test/build.gradle +++ b/shared-test/build.gradle @@ -6,13 +6,17 @@ plugins { android { namespace 'org.openobservatory.ooniprobe.shared.test' - compileSdk 33 + compileSdk libs.versions.compileSdk.get().toInteger() defaultConfig { - minSdk 21 + minSdk libs.versions.minSdk.get().toInteger() } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 + jvmTarget = JavaVersion.VERSION_17 } flavorDimensions = ['testing', 'license'] productFlavors { @@ -60,6 +64,7 @@ dependencies { implementation libs.retrofit.logging.interceptor implementation libs.androidx.appcompat + implementation libs.xanscale.localhost.toolkit testImplementation libs.junit4 androidTestImplementation libs.androidx.junit From 9b41077e89a6d1d4463c57475462c1380ec601bd Mon Sep 17 00:00:00 2001 From: Norbel Ambanumben Date: Sat, 21 Oct 2023 18:17:45 +0100 Subject: [PATCH 5/5] Updated roboelectric --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4c1c32406..9759f49f3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ countlySdk = "21.11.0" faker = "1.2.8" mockitoCore = "5.3.1" mockitoInline = "4.6.1" -robolectric = "4.6.1" +robolectric = "4.10.3" fastlaneScreengrab = "2.0.0" sentryAndroid = "6.3.0" xanscaleLocalhostToolkit = "19.05.01"