diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml new file mode 100644 index 000000000..d41537923 --- /dev/null +++ b/.github/workflows/archive.yml @@ -0,0 +1,19 @@ +# archive creates and publishes an apk for testing +name: archive +on: [push] +jobs: + build: + runs-on: macos-latest + steps: + - uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'temurin' + - name: checkout + uses: actions/checkout@v2 + - run: ./gradlew clean assembleDevFullRelease + - name: uploads dev apk + uses: actions/upload-artifact@v3 + with: + name: dev-apk + path: app/build/outputs/apk/devFull/release \ No newline at end of file diff --git a/NOTICE b/NOTICE index 4b365e82d..5fc016898 100644 --- a/NOTICE +++ b/NOTICE @@ -19,7 +19,6 @@ Terms: https://firebase.google.com/terms/ - easypermissions - LocalhostToolkit -- butterknife - DBFlow - LocalhostToolkit - MarkdownView diff --git a/app/build.gradle b/app/build.gradle index ac15c07d7..5abfe08e1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,19 +1,23 @@ -apply plugin: 'com.android.application' +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} apply from: 'jacoco.gradle' android { - compileSdk 34 + compileSdk libs.versions.compileSdk.get().toInteger() ndkVersion '22.0.7026061' - defaultConfig { - applicationId 'org.openobservatory.ooniprobe' - minSdk 21 - targetSdk 34 + defaultConfig { + applicationId 'org.openobservatory.ooniprobe' + minSdk libs.versions.minSdk.get().toInteger() + targetSdk libs.versions.targetSdk.get().toInteger() versionName '3.8.3' versionCode 102 testInstrumentationRunner "org.openobservatory.ooniprobe.TestAndroidJUnitRunner" buildConfigField 'String', 'OONI_API_BASE_URL', '"https://api.ooni.io/"' buildConfigField 'String', 'NOTIFICATION_SERVER', '"https://countly.ooni.io"' + resValue "string", "APP_ID", 'org.openobservatory.ooniprobe' resValue "string", "APP_NAME", "OONI Probe" buildConfigField 'String', 'SOFTWARE_NAME', 'BASE_SOFTWARE_NAME+IS_DEBUG' buildConfigField 'String', 'COUNTLY_KEY', '"146836f41172f9e3287cab6f2cc347de3f5ddf3b"' @@ -41,18 +45,6 @@ android { } } - // Shared test code between Unit and Instrumented tests - sourceSets { - androidTest { - java.srcDirs += "src/sharedTest/java" - resources.srcDirs += "src/sharedTest/resources" - } - test { - java.srcDirs += "src/sharedTest/java" - resources.srcDirs += "src/sharedTest/resources" - } - } - flavorDimensions 'testing', 'license' productFlavors { stable { @@ -65,6 +57,7 @@ android { versionNameSuffix "-beta.1" versionCode versionCodeDate() buildConfigField 'String', 'BASE_SOFTWARE_NAME', '"ooniprobe-android-dev"' + resValue "string", "APP_ID", 'org.openobservatory.ooniprobe.dev' resValue "string", "APP_NAME", "OONI Dev" buildConfigField 'String', 'COUNTLY_KEY', '"e6c2cfe53e85951d50567467cef3f9fa2eab32c3"' } @@ -74,6 +67,7 @@ android { versionNameSuffix "-experimental.1" versionCode versionCodeDate() buildConfigField 'String', 'BASE_SOFTWARE_NAME', '"ooniprobe-android-experimental"' + resValue "string", "APP_ID", 'org.openobservatory.ooniprobe.experimental' resValue "string", "APP_NAME", "OONI Exp" buildConfigField 'String', 'COUNTLY_KEY', '"e6c2cfe53e85951d50567467cef3f9fa2eab32c3"' } @@ -104,82 +98,75 @@ dependencies { implementation project(path: ':engine') // AndroidX - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.lifecycle:lifecycle-process:2.5.1' - implementation 'androidx.preference:preference:1.2.0' - implementation 'com.google.android.material:material:1.6.1' - implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' - implementation 'com.google.guava:guava:30.1.1-android' - implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation libs.androidx.appcompat + implementation libs.androidx.constraintlayout + implementation libs.androidx.lifecycle.process + implementation libs.androidx.preference + implementation libs.androidx.localbroadcastmanager + implementation libs.androidx.legacy.support.v4 + +// Google + implementation libs.google.material + implementation libs.google.guava + implementation libs.google.gson // Third-party - annotationProcessor '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' - - implementation 'com.squareup.retrofit2:retrofit:2.9.0' - implementation 'com.squareup.retrofit2:converter-gson:2.9.0' - implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1' + annotationProcessor libs.dbflow.processor + implementation libs.dbflow.core + implementation libs.dbflow.lib + implementation libs.retrofit.lib + implementation libs.retrofit.converter.gson + implementation libs.retrofit.logging.interceptor - implementation 'com.jakewharton:butterknife:10.2.3' - annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' - implementation 'com.github.xanscale.LocalhostToolkit:app:19.05.01' - implementation 'com.airbnb.android:lottie:3.0.7' - implementation 'com.google.code.gson:gson:2.8.9' - implementation 'ru.noties:markwon:2.0.1' - implementation 'commons-io:commons-io:2.6' - //arcview to fragment_dashboard - implementation 'com.github.florent37:shapeofview:1.3.2' + implementation libs.xanscale.localhost.toolkit + implementation libs.lottie + implementation libs.markwon + implementation libs.commons.io + //arcview to fragment_dashboard + implementation libs.shapeofview // Flavor - fullImplementation platform('com.google.firebase:firebase-bom:26.3.0') - fullImplementation 'com.google.firebase:firebase-messaging' - fullImplementation 'ly.count.android:sdk:21.11.0' - fullImplementation 'io.sentry:sentry-android:6.3.0' - fullImplementation 'com.google.android.play:core:1.10.3' + fullImplementation platform(libs.google.firebase.bom) + fullImplementation libs.google.firebase.messaging + fullImplementation libs.countly.sdk + fullImplementation libs.sentry.android + fullImplementation libs.google.play.core // Dependency Injection - implementation 'com.google.dagger:dagger:2.36' - annotationProcessor 'com.google.dagger:dagger-compiler:2.36' + implementation libs.google.dagger + annotationProcessor libs.google.dagger.compiler // Logger implementation project(':applogger') // Testing - // Unit Testing - testImplementation 'junit:junit:4.13.2' - testImplementation 'androidx.test:core:1.4.0' - testImplementation 'androidx.test:runner:1.4.0' - testImplementation 'androidx.test:rules:1.4.0' - testImplementation 'org.mockito:mockito-core:4.6.1' - testImplementation 'org.mockito:mockito-inline:4.6.1' - 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' - - // Instrumentation Testing - androidTestImplementation 'tools.fastlane:screengrab:2.0.0' - androidTestImplementation 'com.github.blocoio:faker:1.2.8' - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test:rules:1.4.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' - androidTestImplementation('androidx.test.espresso:espresso-contrib:3.4.0') { - exclude group: 'com.android.support', module: 'appcompat' - exclude group: 'com.android.support', module: 'support-v4' - exclude module: 'recyclerview-v7' - } - androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0') { - exclude group: 'com.android.support', module: 'appcompat' - exclude group: 'com.android.support', module: 'support-v4' - exclude module: 'recyclerview-v7' - } - androidTestImplementation('com.schibsted.spain:barista:3.9.0') - androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.36" + // Unit Testing + testImplementation project(':shared-test') + testImplementation libs.junit4 + testImplementation libs.androidx.core + testImplementation libs.androidx.runner + testImplementation libs.androidx.rules + testImplementation libs.mockito.core + testImplementation libs.mockito.inline + testImplementation libs.robolectric + testImplementation libs.faker + testImplementation libs.ooni.oonimkall + testAnnotationProcessor libs.google.dagger.compiler + + // Instrumentation Testing + androidTestImplementation project(':shared-test') + androidTestImplementation libs.fastlane.screengrab + androidTestImplementation libs.faker + androidTestImplementation libs.androidx.runner + androidTestImplementation libs.androidx.rules + androidTestImplementation libs.androidx.junit + androidTestImplementation libs.androidx.espresso.intents + androidTestImplementation libs.androidx.espresso.contrib + androidTestImplementation libs.androidx.espresso.core + androidTestImplementation libs.barista + androidTestAnnotationProcessor libs.google.dagger.compiler } static def versionCodeDate() { diff --git a/app/jacoco.gradle b/app/jacoco.gradle index 816940653..f75812752 100644 --- a/app/jacoco.gradle +++ b/app/jacoco.gradle @@ -1,7 +1,7 @@ apply plugin: 'jacoco' jacoco { - toolVersion '0.8.5' + toolVersion libs.versions.jacoco.get().toString() } task jacocoAndroidTestReport(type: JacocoReport) { diff --git a/app/src/dev/res/values/untranslatable.xml b/app/src/dev/res/values/untranslatable.xml deleted file mode 100644 index 0a7ae877f..000000000 --- a/app/src/dev/res/values/untranslatable.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - org.openobservatory.ooniprobe.dev.activity.InfoActivity - org.openobservatory.ooniprobe.dev.activity.ProxyActivity - org.openobservatory.ooniprobe.dev.activity.LogActivity - \ No newline at end of file diff --git a/app/src/experimental/res/values/untranslatable.xml b/app/src/experimental/res/values/untranslatable.xml deleted file mode 100644 index 75568c958..000000000 --- a/app/src/experimental/res/values/untranslatable.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - org.openobservatory.ooniprobe.experimental.activity.InfoActivity - org.openobservatory.ooniprobe.experimental.activity.ProxyActivity - org.openobservatory.ooniprobe.experimental.activity.LogActivity - \ No newline at end of file diff --git a/app/src/fdroid/res/xml/preferences_global.xml b/app/src/fdroid/res/xml/preferences_global.xml index 26eea0e6d..3cbcc5cbf 100644 --- a/app/src/fdroid/res/xml/preferences_global.xml +++ b/app/src/fdroid/res/xml/preferences_global.xml @@ -355,7 +355,9 @@ app:iconSpaceReserved="false" android:key="logs" android:title="@string/Settings_Advanced_RecentLogs"> - + - + - + diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/CustomWebsiteActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/CustomWebsiteActivity.java index d4762e534..bef139f13 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/CustomWebsiteActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/CustomWebsiteActivity.java @@ -1,55 +1,42 @@ package org.openobservatory.ooniprobe.activity; import android.content.DialogInterface; -import android.content.Intent; import android.os.Bundle; import android.util.Patterns; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.ImageButton; -import android.widget.LinearLayout; - import androidx.annotation.Nullable; -import androidx.appcompat.widget.Toolbar; -import androidx.core.app.ActivityCompat; - +import localhost.toolkit.app.fragment.ConfirmDialogFragment; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.PreferenceManager; +import org.openobservatory.ooniprobe.databinding.ActivityCustomwebsiteBinding; import org.openobservatory.ooniprobe.model.database.Url; import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import javax.inject.Inject; import java.io.Serializable; import java.util.ArrayList; -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import localhost.toolkit.app.fragment.ConfirmDialogFragment; - public class CustomWebsiteActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener { - @BindView(R.id.urlContainer) - LinearLayout urlContainer; - @BindView(R.id.bottomBar) - Toolbar bottomBar; private ArrayList editTexts; private ArrayList deletes; @Inject PreferenceManager preferenceManager; + private ActivityCustomwebsiteBinding binding; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivityComponent().inject(this); - setContentView(R.layout.activity_customwebsite); - ButterKnife.bind(this); + binding = ActivityCustomwebsiteBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); editTexts = new ArrayList<>(); deletes = new ArrayList<>(); - bottomBar.inflateMenu(R.menu.run); - bottomBar.setOnMenuItemClickListener(item -> { + binding.bottomBar.inflateMenu(R.menu.run); + binding.bottomBar.setOnMenuItemClickListener(item -> { if (!checkPrefix()) return false; ArrayList urls = new ArrayList<>(editTexts.size()); @@ -66,6 +53,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { RunningActivity.runAsForegroundService(CustomWebsiteActivity.this, suite.asArray(), this::finish, preferenceManager); return true; }); + binding.add.setOnClickListener(v -> add()); add(); } @@ -103,12 +91,11 @@ public boolean onSupportNavigateUp() { return true; } - @OnClick(R.id.add) void add() { - ViewGroup urlBox = (ViewGroup) getLayoutInflater().inflate(R.layout.edittext_url, urlContainer, false); + ViewGroup urlBox = (ViewGroup) getLayoutInflater().inflate(R.layout.edittext_url, binding.urlContainer, false); EditText editText = urlBox.findViewById(R.id.editText); editTexts.add(editText); - urlContainer.addView(urlBox); + binding.urlContainer.addView(urlBox); ImageButton delete = urlBox.findViewById(R.id.delete); deletes.add(delete); delete.setTag(editText); @@ -117,11 +104,11 @@ void add() { ((View) v.getParent()).setVisibility(View.GONE); editTexts.remove(tag); deletes.remove(v); - bottomBar.setTitle(getString(R.string.OONIRun_URLs, Integer.toString(editTexts.size()))); + binding.bottomBar.setTitle(getString(R.string.OONIRun_URLs, Integer.toString(editTexts.size()))); setVisibilityDelete(); }); setVisibilityDelete(); - bottomBar.setTitle(getString(R.string.OONIRun_URLs, Integer.toString(editTexts.size()))); + binding.bottomBar.setTitle(getString(R.string.OONIRun_URLs, Integer.toString(editTexts.size()))); } private void setVisibilityDelete() { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/InfoActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/InfoActivity.java index 3a75eace3..b418f26df 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/InfoActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/InfoActivity.java @@ -3,44 +3,40 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.widget.TextView; - import androidx.annotation.Nullable; -import androidx.appcompat.widget.Toolbar; - import org.openobservatory.ooniprobe.BuildConfig; import org.openobservatory.ooniprobe.R; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; +import org.openobservatory.ooniprobe.databinding.ActivityInfoBinding; public class InfoActivity extends AbstractActivity { - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.version) TextView version; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_info); - ButterKnife.bind(this); - setSupportActionBar(toolbar); + ActivityInfoBinding binding = ActivityInfoBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setSupportActionBar(binding.toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - version.setText(getString(R.string.version, BuildConfig.SOFTWARE_NAME, BuildConfig.VERSION_NAME)); + binding.version.setText(getString(R.string.version, BuildConfig.SOFTWARE_NAME, BuildConfig.VERSION_NAME)); + + binding.blog.setOnClickListener(v -> onBlogClick()); + binding.reports.setOnClickListener(v -> onReportsClick()); + binding.learnMore.setOnClickListener(v -> onLearnMoreClick()); + binding.dataPolicy.setOnClickListener(v -> onDataPolicyClick()); } - @OnClick(R.id.blog) void onBlogClick() { + void onBlogClick() { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://ooni.org/blog/"))); } - @OnClick(R.id.reports) void onReportsClick() { + void onReportsClick() { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://ooni.org/reports/"))); } - @OnClick(R.id.learnMore) void onLearnMoreClick() { + void onLearnMoreClick() { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://ooni.org/"))); } - @OnClick(R.id.dataPolicy) void onDataPolicyClick() { + void onDataPolicyClick() { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://ooni.org/about/data-policy/"))); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java index 66650d8dc..933bfbf88 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java @@ -19,7 +19,6 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.core.content.ContextCompat; -import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.snackbar.Snackbar; import org.openobservatory.ooniprobe.R; @@ -38,8 +37,6 @@ import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.app.fragment.ConfirmDialogFragment; public class MainActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener { @@ -71,7 +68,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { finish(); } else { - ButterKnife.bind(this); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); binding.bottomNavigation.setOnItemSelectedListener(item -> { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/MeasurementDetailActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/MeasurementDetailActivity.java index 1e00ceb1d..91bdc4dfd 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/MeasurementDetailActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/MeasurementDetailActivity.java @@ -8,87 +8,41 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.Button; -import android.widget.TextView; - import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.fragment.app.Fragment; - import com.google.android.material.snackbar.Snackbar; import com.google.gson.Gson; - +import localhost.toolkit.app.fragment.ConfirmDialogFragment; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.ResubmitTask; +import org.openobservatory.ooniprobe.databinding.ActivityMeasurementDetailBinding; import org.openobservatory.ooniprobe.domain.GetTestSuite; import org.openobservatory.ooniprobe.domain.MeasurementsManager; import org.openobservatory.ooniprobe.domain.callback.DomainCallback; -import org.openobservatory.ooniprobe.fragment.measurement.DashFragment; -import org.openobservatory.ooniprobe.fragment.measurement.FacebookMessengerFragment; -import org.openobservatory.ooniprobe.fragment.measurement.FailedFragment; -import org.openobservatory.ooniprobe.fragment.measurement.HeaderNdtFragment; -import org.openobservatory.ooniprobe.fragment.measurement.HeaderOutcomeFragment; -import org.openobservatory.ooniprobe.fragment.measurement.HttpHeaderFieldManipulationFragment; -import org.openobservatory.ooniprobe.fragment.measurement.HttpInvalidRequestLineFragment; -import org.openobservatory.ooniprobe.fragment.measurement.NdtFragment; -import org.openobservatory.ooniprobe.fragment.measurement.PsiphonFragment; -import org.openobservatory.ooniprobe.fragment.measurement.RiseupVPNFragment; -import org.openobservatory.ooniprobe.fragment.measurement.SignalFragment; -import org.openobservatory.ooniprobe.fragment.measurement.TelegramFragment; -import org.openobservatory.ooniprobe.fragment.measurement.TorFragment; -import org.openobservatory.ooniprobe.fragment.measurement.WebConnectivityFragment; -import org.openobservatory.ooniprobe.fragment.measurement.WhatsappFragment; +import org.openobservatory.ooniprobe.fragment.measurement.*; import org.openobservatory.ooniprobe.fragment.resultHeader.ResultHeaderDetailFragment; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.test.suite.PerformanceSuite; -import org.openobservatory.ooniprobe.test.test.Dash; -import org.openobservatory.ooniprobe.test.test.FacebookMessenger; -import org.openobservatory.ooniprobe.test.test.HttpHeaderFieldManipulation; -import org.openobservatory.ooniprobe.test.test.HttpInvalidRequestLine; -import org.openobservatory.ooniprobe.test.test.Ndt; -import org.openobservatory.ooniprobe.test.test.Psiphon; -import org.openobservatory.ooniprobe.test.test.RiseupVPN; -import org.openobservatory.ooniprobe.test.test.Signal; -import org.openobservatory.ooniprobe.test.test.Telegram; -import org.openobservatory.ooniprobe.test.test.Tor; -import org.openobservatory.ooniprobe.test.test.WebConnectivity; -import org.openobservatory.ooniprobe.test.test.Whatsapp; +import org.openobservatory.ooniprobe.test.test.*; +import ru.noties.markwon.Markwon; +import javax.inject.Inject; import java.io.Serializable; import java.util.Collections; import java.util.Objects; -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import localhost.toolkit.app.fragment.ConfirmDialogFragment; -import ru.noties.markwon.Markwon; - public class MeasurementDetailActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener { private static final String ID = "id"; private static final String RERUN_KEY = "rerun"; - @BindView(R.id.coordinatorLayout) - CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar) - Toolbar toolbar; + private Boolean isInExplorer; + private Measurement measurement; + private Snackbar snackbar; - private Boolean isInExplorer; - @BindView(R.id.log) - Button log; - @BindView(R.id.explorer) - Button explorer; - @BindView(R.id.data) - Button data; - @BindView(R.id.methodology) - TextView methodology; @Inject MeasurementsManager measurementsManager; @@ -121,9 +75,9 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { measurement.is_anomaly ? R.style.Theme_MaterialComponents_Light_DarkActionBar_App_NoActionBar_Failure : R.style.Theme_MaterialComponents_Light_DarkActionBar_App_NoActionBar_Success); - setContentView(R.layout.activity_measurement_detail); - ButterKnife.bind(this); - setSupportActionBar(toolbar); + ActivityMeasurementDetailBinding binding = ActivityMeasurementDetailBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setSupportActionBar(binding.toolbar); ActionBar bar = getSupportActionBar(); if (bar != null) { bar.setDisplayHomeAsUpEnabled(true); @@ -237,7 +191,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { .replace(R.id.body, detail) .replace(R.id.head, head) .commit(); - snackbar = Snackbar.make(coordinatorLayout, R.string.Snackbar_ResultsNotUploaded_Text, Snackbar.LENGTH_INDEFINITE) + snackbar = Snackbar.make(binding.coordinatorLayout, R.string.Snackbar_ResultsNotUploaded_Text, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.Snackbar_ResultsNotUploaded_Upload, v1 -> runAsyncTask()); Context c = this; isInExplorer = !measurement.hasReportFile(c); @@ -255,11 +209,14 @@ public void onError(String msg) { }); if (!measurement.hasLogFile(this)) - log.setVisibility(View.GONE); + binding.log.setVisibility(View.GONE); if (!measurementsManager.hasReportId(measurement)) - explorer.setVisibility(View.GONE); - Markwon.setMarkdown(methodology, getString(R.string.TestResults_Details_Methodology_Paragraph, getString(measurement.getTest().getUrlResId()))); + binding.explorer.setVisibility(View.GONE); + Markwon.setMarkdown(binding.methodology, getString(R.string.TestResults_Details_Methodology_Paragraph, getString(measurement.getTest().getUrlResId()))); load(); + binding.log.setOnClickListener(v -> logClick()); + binding.data.setOnClickListener(v -> dataClick()); + binding.explorer.setOnClickListener(v -> explorerClick()); } private void runAsyncTask() { @@ -305,17 +262,14 @@ public boolean onOptionsItemSelected(MenuItem item) { } } - @OnClick(R.id.log) void logClick() { startActivity(TextActivity.newIntent(this, TextActivity.TYPE_LOG, measurement)); } - @OnClick(R.id.data) void dataClick() { startActivity(TextActivity.newIntent(this, TextActivity.TYPE_JSON, measurement)); } - @OnClick(R.id.explorer) void explorerClick() { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(measurementsManager.getExplorerUrl(measurement)))); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/OoniRunActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/OoniRunActivity.java index 89b32b674..50613aecf 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/OoniRunActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/OoniRunActivity.java @@ -6,21 +6,17 @@ import android.util.Patterns; import android.view.View; import android.webkit.URLUtil; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; import android.widget.Toast; -import androidx.appcompat.widget.Toolbar; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import com.google.gson.Gson; import org.openobservatory.ooniprobe.BuildConfig; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.PreferenceManager; +import org.openobservatory.ooniprobe.databinding.ActivityOonirunBinding; import org.openobservatory.ooniprobe.domain.GetTestSuite; import org.openobservatory.ooniprobe.domain.VersionCompare; import org.openobservatory.ooniprobe.domain.models.Attribute; @@ -33,19 +29,11 @@ import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerAdapter; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class OoniRunActivity extends AbstractActivity { - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.icon) ImageView icon; - @BindView(R.id.iconBig) ImageView iconBig; - @BindView(R.id.title) TextView title; - @BindView(R.id.desc) TextView desc; - @BindView(R.id.run) Button run; - @BindView(R.id.recycler) RecyclerView recycler; + ActivityOonirunBinding binding; private ArrayList items; private HeterogeneousRecyclerAdapter adapter; @@ -65,17 +53,17 @@ public class OoniRunActivity extends AbstractActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivityComponent().inject(this); - setContentView(R.layout.activity_oonirun); - ButterKnife.bind(this); - setSupportActionBar(toolbar); + binding = ActivityOonirunBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setSupportActionBar(binding.toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); LinearLayoutManager layoutManager = new LinearLayoutManager(this); - recycler.setLayoutManager(layoutManager); - recycler.addItemDecoration(new DividerItemDecoration(this, layoutManager.getOrientation())); + binding.recycler.setLayoutManager(layoutManager); + binding.recycler.addItemDecoration(new DividerItemDecoration(this, layoutManager.getOrientation())); items = new ArrayList<>(); adapter = new HeterogeneousRecyclerAdapter<>(this, items); - recycler.setAdapter(adapter); + binding.recycler.setAdapter(adapter); manageIntent(getIntent()); } @@ -139,34 +127,34 @@ private void loadScreen(String mv, String tn, String ta){ } private void loadOutOfDate() { - title.setText(R.string.OONIRun_OONIProbeOutOfDate); - desc.setText(R.string.OONIRun_OONIProbeNewerVersion); - run.setText(R.string.OONIRun_Update); - icon.setImageResource(R.drawable.update); - iconBig.setImageResource(R.drawable.update); - iconBig.setVisibility(View.VISIBLE); - run.setOnClickListener(v -> { + binding.title.setText(R.string.OONIRun_OONIProbeOutOfDate); + binding.desc.setText(R.string.OONIRun_OONIProbeNewerVersion); + binding.run.setText(R.string.OONIRun_Update); + binding.icon.setImageResource(R.drawable.update); + binding.iconBig.setImageResource(R.drawable.update); + binding.iconBig.setVisibility(View.VISIBLE); + binding.run.setOnClickListener(v -> { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName()))); finish(); }); } private void loadSuite(AbstractSuite suite, List urls) { - icon.setImageResource(suite.getIcon()); - title.setText(suite.getTestList(preferenceManager)[0].getLabelResId()); - desc.setText(getString(R.string.OONIRun_YouAreAboutToRun)); + binding.icon.setImageResource(suite.getIcon()); + binding.title.setText(suite.getTestList(preferenceManager)[0].getLabelResId()); + binding.desc.setText(getString(R.string.OONIRun_YouAreAboutToRun)); if (urls != null) { for (String url : urls) { if (URLUtil.isValidUrl(url)) items.add(new TextItem(url)); } adapter.notifyTypesChanged(); - iconBig.setVisibility(View.GONE); + binding.iconBig.setVisibility(View.GONE); } else { - iconBig.setImageResource(suite.getIcon()); - iconBig.setVisibility(View.VISIBLE); + binding.iconBig.setImageResource(suite.getIcon()); + binding.iconBig.setVisibility(View.VISIBLE); } - run.setOnClickListener(v -> { + binding.run.setOnClickListener(v -> { RunningActivity.runAsForegroundService(OoniRunActivity.this, suite.asArray(),this::finish, preferenceManager); @@ -174,12 +162,12 @@ private void loadSuite(AbstractSuite suite, List urls) { } private void loadInvalidAttributes() { - title.setText(R.string.OONIRun_InvalidParameter); - desc.setText(R.string.OONIRun_InvalidParameter_Msg); - run.setText(R.string.OONIRun_Close); - icon.setImageResource(R.drawable.question_mark); - iconBig.setImageResource(R.drawable.question_mark); - iconBig.setVisibility(View.VISIBLE); - run.setOnClickListener(v -> finish()); + binding.title.setText(R.string.OONIRun_InvalidParameter); + binding.desc.setText(R.string.OONIRun_InvalidParameter_Msg); + binding.run.setText(R.string.OONIRun_Close); + binding.icon.setImageResource(R.drawable.question_mark); + binding.iconBig.setImageResource(R.drawable.question_mark); + binding.iconBig.setVisibility(View.VISIBLE); + binding.run.setOnClickListener(v -> finish()); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java index 415744384..d7b9c4997 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java @@ -5,18 +5,14 @@ import android.os.Bundle; import android.text.format.DateUtils; import android.view.View; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; import androidx.annotation.Nullable; -import androidx.appcompat.widget.Toolbar; -import androidx.core.app.ActivityCompat; import androidx.core.text.TextUtilsCompat; import androidx.core.view.ViewCompat; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.PreferenceManager; +import org.openobservatory.ooniprobe.databinding.ActivityOverviewBinding; import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite; @@ -27,20 +23,12 @@ import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; import ru.noties.markwon.Markwon; public class OverviewActivity extends AbstractActivity { private static final String TEST = "test"; - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.icon) ImageView icon; - @BindView(R.id.runtime) TextView runtime; - @BindView(R.id.lastTime) TextView lastTime; - @BindView(R.id.desc) TextView desc; - @BindView(R.id.customUrl) Button customUrl; - @BindView(R.id.run) Button run; + + ActivityOverviewBinding binding; private AbstractSuite testSuite; @Inject @@ -55,16 +43,16 @@ public static Intent newIntent(Context context, AbstractSuite testSuite) { getActivityComponent().inject(this); testSuite = (AbstractSuite) getIntent().getSerializableExtra(TEST); setTheme(testSuite.getThemeLight()); - setContentView(R.layout.activity_overview); - ButterKnife.bind(this); - setSupportActionBar(toolbar); + binding = ActivityOverviewBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setSupportActionBar(binding.toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); setTitle(testSuite.getTitle()); - icon.setImageResource(testSuite.getIcon()); - customUrl.setVisibility(testSuite.getName().equals(WebsitesSuite.NAME) ? View.VISIBLE : View.GONE); + binding.icon.setImageResource(testSuite.getIcon()); + binding.customUrl.setVisibility(testSuite.getName().equals(WebsitesSuite.NAME) ? View.VISIBLE : View.GONE); if(testSuite.isTestEmpty(preferenceManager)){ - run.setAlpha(0.5F); - run.setEnabled(false); + binding.run.setAlpha(0.5F); + binding.run.setEnabled(false); } if (testSuite.getName().equals(ExperimentalSuite.NAME)) { String experimentalLinks = @@ -72,24 +60,31 @@ public static Intent newIntent(Context context, AbstractSuite testSuite) { "\n\n* [DNS Check](https://github.com/ooni/spec/blob/master/nettests/ts-028-dnscheck.md)" + "\n\n* [Tor Snowflake](https://ooni.org/nettest/tor-snowflake/) "+ String.format(" ( %s )",getString(R.string.Settings_TestOptions_LongRunningTest))+ "\n\n* [Vanilla Tor](https://github.com/ooni/spec/blob/master/nettests/ts-016-vanilla-tor.md) " + String.format(" ( %s )",getString(R.string.Settings_TestOptions_LongRunningTest)); - Markwon.setMarkdown(desc, getString(testSuite.getDesc1(), experimentalLinks)); + Markwon.setMarkdown(binding.desc, getString(testSuite.getDesc1(), experimentalLinks)); if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL) - desc.setTextDirection(View.TEXT_DIRECTION_RTL); + binding.desc.setTextDirection(View.TEXT_DIRECTION_RTL); } else - Markwon.setMarkdown(desc, getString(testSuite.getDesc1())); + Markwon.setMarkdown(binding.desc, getString(testSuite.getDesc1())); Result lastResult = Result.getLastResult(testSuite.getName()); if (lastResult == null) - lastTime.setText(R.string.Dashboard_Overview_LastRun_Never); + binding.lastTime.setText(R.string.Dashboard_Overview_LastRun_Never); else - lastTime.setText(DateUtils.getRelativeTimeSpanString(lastResult.start_time.getTime())); + binding.lastTime.setText(DateUtils.getRelativeTimeSpanString(lastResult.start_time.getTime())); + + setUpOnCLickListeners(); + } + + private void setUpOnCLickListeners() { + binding.run.setOnClickListener(view -> onRunClick()); + binding.customUrl.setOnClickListener(view -> customUrlClick()); } @Override protected void onResume() { super.onResume(); testSuite.setTestList((AbstractTest[]) null); testSuite.getTestList(preferenceManager); - runtime.setText(getString(R.string.twoParam, getString(testSuite.getDataUsage()), getString(R.string.Dashboard_Card_Seconds, testSuite.getRuntime(preferenceManager).toString()))); + binding.runtime.setText(getString(R.string.twoParam, getString(testSuite.getDataUsage()), getString(R.string.Dashboard_Card_Seconds, testSuite.getRuntime(preferenceManager).toString()))); } @Override @@ -98,13 +93,13 @@ public boolean onSupportNavigateUp() { return true; } - @OnClick(R.id.run) void onRunClick() { + void onRunClick() { if(!testSuite.isTestEmpty(preferenceManager)){ RunningActivity.runAsForegroundService(this, testSuite.asArray(), this::bindTestService, preferenceManager); } } - @OnClick(R.id.customUrl) void customUrlClick() { + void customUrlClick() { startActivity(new Intent(this, CustomWebsiteActivity.class)); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/ResultDetailActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/ResultDetailActivity.java index 15e334152..e80a6fafb 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/ResultDetailActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/ResultDetailActivity.java @@ -7,27 +7,23 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; - import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager2.adapter.FragmentStateAdapter; -import androidx.viewpager2.widget.ViewPager2; - import com.google.android.material.snackbar.Snackbar; -import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; - +import localhost.toolkit.app.fragment.ConfirmDialogFragment; +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerAdapter; +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.ResubmitTask; +import org.openobservatory.ooniprobe.databinding.ActivityResultDetailBinding; import org.openobservatory.ooniprobe.domain.GetResults; import org.openobservatory.ooniprobe.domain.GetTestSuite; import org.openobservatory.ooniprobe.fragment.resultHeader.ResultHeaderDetailFragment; @@ -39,39 +35,18 @@ import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.model.database.Result; -import org.openobservatory.ooniprobe.test.suite.CircumventionSuite; -import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite; -import org.openobservatory.ooniprobe.test.suite.InstantMessagingSuite; -import org.openobservatory.ooniprobe.test.suite.MiddleBoxesSuite; -import org.openobservatory.ooniprobe.test.suite.PerformanceSuite; -import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import org.openobservatory.ooniprobe.test.suite.*; +import javax.inject.Inject; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.app.fragment.ConfirmDialogFragment; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerAdapter; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class ResultDetailActivity extends AbstractActivity implements View.OnClickListener, ConfirmDialogFragment.OnConfirmedListener { private static final String ID = "id"; private static final String UPLOAD_KEY = "upload"; private static final String RERUN_KEY = "rerun"; - @BindView(R.id.coordinatorLayout) - CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar) - Toolbar toolbar; - @BindView(R.id.tabLayout) - TabLayout tabLayout; - @BindView(R.id.pager) - ViewPager2 pager; - @BindView(R.id.recyclerView) - RecyclerView recycler; + private ArrayList items; private HeterogeneousRecyclerAdapter adapter; private Result result; @@ -97,27 +72,27 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { result = getResults.get(getIntent().getIntExtra(ID, 0)); assert result != null; setTheme(result.getTestSuite().getThemeLight()); - setContentView(R.layout.activity_result_detail); - ButterKnife.bind(this); - setSupportActionBar(toolbar); + ActivityResultDetailBinding binding = ActivityResultDetailBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setSupportActionBar(binding.toolbar); ActionBar bar = getSupportActionBar(); if (bar != null) { bar.setDisplayHomeAsUpEnabled(true); bar.setTitle(result.getTestSuite().getTitle()); } - pager.setAdapter(new ResultHeaderAdapter(this)); - new TabLayoutMediator(tabLayout, pager, (tab, position) -> + binding.pager.setAdapter(new ResultHeaderAdapter(this)); + new TabLayoutMediator(binding.tabLayout, binding.pager, (tab, position) -> tab.setText("●") ).attach(); LinearLayoutManager layoutManager = new LinearLayoutManager(this); - recycler.setLayoutManager(layoutManager); - recycler.addItemDecoration(new DividerItemDecoration(this, layoutManager.getOrientation())); + binding.recyclerView.setLayoutManager(layoutManager); + binding.recyclerView.addItemDecoration(new DividerItemDecoration(this, layoutManager.getOrientation())); result.is_viewed = true; result.save(); items = new ArrayList<>(); adapter = new HeterogeneousRecyclerAdapter<>(this, items); - recycler.setAdapter(adapter); - snackbar = Snackbar.make(coordinatorLayout, R.string.Snackbar_ResultsSomeNotUploaded_Text, Snackbar.LENGTH_INDEFINITE) + binding.recyclerView.setAdapter(adapter); + snackbar = Snackbar.make(binding.coordinatorLayout, R.string.Snackbar_ResultsSomeNotUploaded_Text, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.Snackbar_ResultsSomeNotUploaded_UploadAll, v1 -> runAsyncTask()); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index d40d95dcb..c65b13df1 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -12,20 +12,12 @@ import android.os.Bundle; import android.view.View; import android.view.animation.Animation; -import android.widget.Button; -import android.widget.ImageButton; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; -import com.airbnb.lottie.LottieAnimationView; - import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.PreferenceManager; @@ -33,6 +25,7 @@ import org.openobservatory.ooniprobe.common.TestProgressRepository; import org.openobservatory.ooniprobe.common.service.RunTestService; import org.openobservatory.ooniprobe.common.service.ServiceUtil; +import org.openobservatory.ooniprobe.databinding.ActivityRunningBinding; import org.openobservatory.ooniprobe.receiver.TestRunBroadRequestReceiver; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite; @@ -42,36 +35,19 @@ import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.app.fragment.ConfirmDialogFragment; import localhost.toolkit.app.fragment.MessageDialogFragment; /** - * Serves to display progress of {@code RunTestService} running in in the background on a screen. + * Serves to display progress of {@code RunTestService} running in the background on a screen. * * Also contains {@link #runAsForegroundService(AbstractActivity, ArrayList,OnTestServiceStartedListener) runAsForegroundService} * used to start {@code RunTestService} in the background. */ public class RunningActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener { - @BindView(R.id.running) - TextView running; - @BindView(R.id.name) - TextView name; - @BindView(R.id.log) - TextView log; - @BindView(R.id.eta) - TextView eta; - @BindView(R.id.progress) - ProgressBar progress; - @BindView(R.id.close) - ImageButton close; - @BindView(R.id.stop) - Button stop; - @BindView(R.id.animation) - LottieAnimationView animation; - @BindView(R.id.proxy_icon) - RelativeLayout proxy_icon; + + ActivityRunningBinding binding; + private TestRunBroadRequestReceiver receiver; @Inject @@ -127,7 +103,7 @@ public static void runAsForegroundService(AbstractActivity context, private static void startRunTestService(AbstractActivity context, ArrayList testSuites, OnTestServiceStartedListener onTestServiceStartedListener) { - ServiceUtil.startRunTestService(context, testSuites, true); + ServiceUtil.startRunTestServiceManual(context, testSuites, true); onTestServiceStartedListener.onTestServiceStarted(); } @@ -136,29 +112,29 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivityComponent().inject(this); setTheme(R.style.Theme_MaterialComponents_NoActionBar_App); - setContentView(R.layout.activity_running); - ButterKnife.bind(this); + binding = ActivityRunningBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); testProgressRepository.getProgress().observe(this, progressValue -> { if (progressValue!=null) { - progress.setProgress(progressValue); + binding.progress.setProgress(progressValue); } }); testProgressRepository.getEta().observe(this,etaValue -> { if (etaValue!=null) { - eta.setText(readableTimeRemaining(etaValue)); + binding.eta.setText(readableTimeRemaining(etaValue)); } }); if (preferenceManager.getProxyURL().isEmpty()) - proxy_icon.setVisibility(View.GONE); - close.setOnClickListener(new View.OnClickListener() { + binding.proxyIcon.setVisibility(View.GONE); + binding.close.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { finish(); } }); - stop.setOnClickListener(new View.OnClickListener() { + binding.stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new ConfirmDialogFragment.Builder() @@ -176,33 +152,33 @@ private void applyUIChanges(RunTestService service) { service.task.currentSuite == null || service.task.currentTest == null) { return; } - animation.setImageAssetsFolder("anim/"); - animation.setRepeatCount(Animation.INFINITE); - animation.playAnimation(); + binding.animation.setImageAssetsFolder("anim/"); + binding.animation.setRepeatCount(Animation.INFINITE); + binding.animation.playAnimation(); Integer progressLevel = testProgressRepository.getProgress().getValue(); if (progressLevel != null) { - progress.setProgress(progressLevel); + binding.progress.setProgress(progressLevel); } else { - progress.setIndeterminate(true); + binding.progress.setIndeterminate(true); } Double etaValue = testProgressRepository.getEta().getValue(); if (etaValue!=null){ - eta.setText(readableTimeRemaining(etaValue)); + binding.eta.setText(readableTimeRemaining(etaValue)); }else { - eta.setText(R.string.Dashboard_Running_CalculatingETA); + binding.eta.setText(R.string.Dashboard_Running_CalculatingETA); } if (service.task.currentSuite.getName().equals(ExperimentalSuite.NAME)) - name.setText(service.task.currentTest.getName()); + binding.name.setText(service.task.currentTest.getName()); else - name.setText(getString(service.task.currentTest.getLabelResId())); + binding.name.setText(getString(service.task.currentTest.getLabelResId())); getWindow().setBackgroundDrawableResource(service.task.currentSuite.getColor()); if (Build.VERSION.SDK_INT >= 21) { getWindow().setStatusBarColor(service.task.currentSuite.getColor()); } - animation.setAnimation(service.task.currentSuite.getAnim()); - progress.setMax(service.task.getMax(preferenceManager)); + binding.animation.setAnimation(service.task.currentSuite.getAnim()); + binding.progress.setMax(service.task.getMax(preferenceManager)); } @Override @@ -264,20 +240,20 @@ public void onStart(RunTestService service) { @Override public void onRun(String value) { - name.setText(value); + binding.name.setText(value); } @Override public void onProgress(int state, double timeLeft) { - progress.setIndeterminate(false); - progress.setProgress(state); + binding.progress.setIndeterminate(false); + binding.progress.setProgress(state); - eta.setText(readableTimeRemaining(timeLeft)); + binding.eta.setText(readableTimeRemaining(timeLeft)); } @Override public void onLog(String value) { - log.setText(value); + binding.log.setText(value); } @Override @@ -287,13 +263,13 @@ public void onError(String value) { @Override public void onUrl() { - progress.setIndeterminate(false); + binding.progress.setIndeterminate(false); } @Override public void onInterrupt() { - running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); - log.setText(getString(R.string.Dashboard_Running_Stopping_Notice)); + binding.running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); + binding.log.setText(getString(R.string.Dashboard_Running_Stopping_Notice)); } @Override diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/TextActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/TextActivity.java index c13cc269d..94798e09a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/TextActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/TextActivity.java @@ -7,24 +7,19 @@ import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; -import android.widget.TextView; import android.widget.Toast; - import androidx.annotation.Nullable; import androidx.fragment.app.FragmentManager; - +import localhost.toolkit.app.fragment.MessageDialogFragment; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.ReachabilityManager; +import org.openobservatory.ooniprobe.databinding.TextBinding; import org.openobservatory.ooniprobe.domain.MeasurementsManager; import org.openobservatory.ooniprobe.domain.callback.DomainCallback; import org.openobservatory.ooniprobe.model.database.Measurement; import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.app.fragment.MessageDialogFragment; - public class TextActivity extends AbstractActivity { private Measurement measurement; private String text; @@ -34,8 +29,7 @@ public class TextActivity extends AbstractActivity { private static final String TEST = "test"; private static final String TYPE = "type"; private static final String TEXT = "text"; - @BindView(R.id.textView) - TextView textView; + private TextBinding binding; @Inject MeasurementsManager measurementsManager; @@ -52,8 +46,8 @@ public static Intent newIntent(Context context, int type, String text) { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivityComponent().inject(this); - setContentView(R.layout.text); - ButterKnife.bind(this); + binding = TextBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); showText(); } @@ -95,7 +89,7 @@ public void showText() { private void showLog() { try { text = measurementsManager.getReadableLog(measurement); - textView.setText(text); + binding.textView.setText(text); } catch (Exception e) { new MessageDialogFragment.Builder() .withTitle(getString(R.string.Modal_Error_LogNotFound)) @@ -107,7 +101,7 @@ private void showJson() { //Try to open file, if it doesn't exist dont show Error dialog immediately but try to download the json from internet try { text = measurementsManager.getReadableEntry(measurement); - textView.setText(text); + binding.textView.setText(text); } catch (Exception e) { e.printStackTrace(); if (ReachabilityManager.getNetworkType(this).equals(ReachabilityManager.NO_INTERNET)) { @@ -125,7 +119,7 @@ private void showJson() { public void onSuccess(String result) { runOnUiThread(() -> { text = result; - textView.setText(result); + binding.textView.setText(result); }); } @@ -140,7 +134,7 @@ public void onError(String msg) { } private void showUploadLog() { - textView.setText(text); + binding.textView.setText(text); } private void showError(String msg) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java index 2df95f322..37fe91292 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java @@ -34,7 +34,7 @@ public JobTask(JobService jobService, Application app) { @Override protected JobParameters doInBackground(JobParameters... params) { - ServiceUtil.callCheckInAPI(app); + ServiceUtil.startRunTestServiceUnattended(app); return params[0]; } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index a7d3e2259..d35a95798 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -62,6 +62,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { if (testSuites == null || testSuites.size() == 0) return START_STICKY_COMPATIBILITY; boolean store_db = intent.getBooleanExtra("storeDB", true); + boolean unattended = intent.getBooleanExtra("unattended", false); Application app = ((Application) getApplication()); NotificationUtility.setChannel(getApplicationContext(), CHANNEL_ID, app.getString(R.string.Settings_AutomatedTesting_Label), false, false, false); Intent notificationIntent = new Intent(this, RunningActivity.class); @@ -79,7 +80,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { .setProgress(100, 0, false) .build(); - task = (TestAsyncTask) new TestAsyncTask(app, testSuites, store_db).execute(); + task = (TestAsyncTask) new TestAsyncTask(app, testSuites, store_db, unattended).execute(); //This intent is used to manage the stop test button in the notification Intent broadcastIntent = new Intent(); broadcastIntent.setAction(RunTestService.ACTION_INTERRUPT); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java index 82b1895de..1f7c0e9e7 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java @@ -68,7 +68,7 @@ public static void stopJob(Context context) { } } - public static void callCheckInAPI(Application app) { + public static void startRunTestServiceUnattended(Application app) { app.getServiceComponent().inject(d); boolean isVPNInUse = ReachabilityManager.isVPNinUse(app); @@ -79,20 +79,24 @@ public static void callCheckInAPI(Application app) { return; } - - AbstractSuite suite = d.generateAutoRunServiceSuite.generate(config); + AbstractSuite suite = d.generateAutoRunServiceSuite.generate(); ArrayList testSuites = new ArrayList<>(); testSuites.add(suite); testSuites.add(InstantMessagingSuite.initForAutoRun()); testSuites.add(CircumventionSuite.initForAutoRun()); testSuites.add(PerformanceSuite.initForAutoRun()); testSuites.add(ExperimentalSuite.initForAutoRun()); - ServiceUtil.startRunTestService(app, testSuites, false); + ServiceUtil.startRunTestServiceCommon(app, testSuites, false, true); + d.generateAutoRunServiceSuite.markAsRan(); } - public static void startRunTestService(Context context, ArrayList iTestSuites, boolean storeDB) { + public static void startRunTestServiceManual(Context context, ArrayList iTestSuites, boolean storeDB) { + startRunTestServiceCommon(context, iTestSuites, storeDB, false); + } + + private static void startRunTestServiceCommon(Context context, ArrayList iTestSuites, boolean storeDB, boolean unattended) { ArrayList testSuites = Lists.newArrayList( Iterables.filter(Iterables.filter(iTestSuites, item -> item != null), testSuite -> !testSuite.isTestEmpty(d.preferenceManager)) ); @@ -100,6 +104,7 @@ public static void startRunTestService(Context context, ArrayList Intent serviceIntent = new Intent(context, RunTestService.class); serviceIntent.putExtra("testSuites", testSuites); serviceIntent.putExtra("storeDB", storeDB); + serviceIntent.putExtra("unattended", unattended); ContextCompat.startForegroundService(context, serviceIntent); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuite.java b/app/src/main/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuite.java index b7c4b2579..a511b847e 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuite.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuite.java @@ -31,47 +31,17 @@ public class GenerateAutoRunServiceSuite { this.app = application; } - public AbstractSuite generate( - OONICheckInConfig config - ) { - - try { - OONISession session = EngineProvider.get().newSession( - EngineProvider.get().getDefaultSessionConfig( - app, - String.join("-",BuildConfig.SOFTWARE_NAME, AbstractTest.UNATTENDED), - BuildConfig.VERSION_NAME, - new LoggerArray(), - pm.getProxyURL() - ) - ); - OONIContext ooniContext = session.newContextWithTimeout(30); - OONICheckInResults results = session.checkIn(ooniContext, config); - - if (results.getWebConnectivity() != null) { - List inputs = new ArrayList<>(); - for (OONIURLInfo url : results.getWebConnectivity().getUrls()) { - inputs.add(url.getUrl()); - } - - markAsRan(); - - return AbstractSuite.getSuite( - app, - "web_connectivity", - inputs, - AbstractTest.AUTORUN - ); - } - - return null; - } catch (Exception e) { - e.printStackTrace(); - ThirdPartyServices.logException(e); - return null; - } + public AbstractSuite generate() { + + return AbstractSuite.getSuite( + app, + "web_connectivity", + null, + AbstractTest.AUTORUN + ); } + public boolean shouldStart(Boolean isWifi, Boolean isCharging, Boolean isVPNInUse) { if (pm.testWifiOnly() && !isWifi) return false; @@ -86,7 +56,7 @@ public boolean shouldStart(Boolean isWifi, Boolean isCharging, Boolean isVPNInUs return true; } - private void markAsRan() { + public void markAsRan() { pm.updateAutorunDate(); pm.incrementAutorun(); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java index 0ebeb4d8d..7eee1ca50 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java @@ -1,31 +1,27 @@ package org.openobservatory.ooniprobe.fragment; -import android.content.Intent; import android.os.Bundle; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.activity.AbstractActivity; -import org.openobservatory.ooniprobe.activity.MainActivity; 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; @@ -33,43 +29,38 @@ import org.openobservatory.ooniprobe.test.suite.AbstractSuite; import java.util.ArrayList; -import java.util.Objects; import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerAdapter; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class DashboardFragment extends Fragment implements View.OnClickListener { - @BindView(R.id.recycler) RecyclerView recycler; - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.last_tested) TextView lastTested; - @BindView(R.id.run_all) TextView runAll; - @BindView(R.id.vpn) TextView vpn; @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) { - View v = inflater.inflate(R.layout.fragment_dashboard, container, false); - ButterKnife.bind(this, v); + binding = FragmentDashboardBinding.inflate(inflater,container,false); ((Application) getActivity().getApplication()).getFragmentComponent().inject(this); - ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); + ((AppCompatActivity) getActivity()).setSupportActionBar(binding.toolbar); ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(null); items = new ArrayList<>(); testSuites = new ArrayList<>(); adapter = new HeterogeneousRecyclerAdapter<>(getActivity(), items); - recycler.setAdapter(adapter); - recycler.setLayoutManager(new LinearLayoutManager(getActivity())); - runAll.setOnClickListener(v1 -> runAll()); - vpn.setOnClickListener(view -> ((Application) getActivity().getApplication()).openVPNSettings()); - return v; + 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() { @@ -100,19 +91,19 @@ public class DashboardFragment extends Fragment implements View.OnClickListener adapter.notifyTypesChanged(); if (ReachabilityManager.isVPNinUse(this.getContext()) && preferenceManager.isWarnVPNInUse()) - vpn.setVisibility(View.VISIBLE); + binding.vpn.setVisibility(View.VISIBLE); else - vpn.setVisibility(View.GONE); + binding.vpn.setVisibility(View.GONE); } private void setLastTest() { Result lastResult = Result.getLastResult(); if (lastResult == null) - lastTested.setText(getString(R.string.Dashboard_Overview_LatestTest) + binding.lastTested.setText(getString(R.string.Dashboard_Overview_LatestTest) + " " + getString(R.string.Dashboard_Overview_LastRun_Never)); else - lastTested.setText(getString(R.string.Dashboard_Overview_LatestTest) + binding.lastTested.setText(getString(R.string.Dashboard_Overview_LatestTest) + " " + DateUtils.getRelativeTimeSpanString(lastResult.start_time.getTime())); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.java index a4f948a15..b37840428 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.java @@ -5,50 +5,35 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; - -import androidx.core.app.ActivityCompat; -import androidx.fragment.app.Fragment; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; - import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - +import androidx.core.app.ActivityCompat; +import androidx.fragment.app.Fragment; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.TestProgressRepository; import org.openobservatory.ooniprobe.common.service.RunTestService; +import org.openobservatory.ooniprobe.databinding.FragmentProgressBinding; import org.openobservatory.ooniprobe.receiver.TestRunBroadRequestReceiver; import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; - /** * Monitors and displays progress of {@link RunTestService}. */ public class ProgressFragment extends Fragment { private TestRunBroadRequestReceiver receiver; + private FragmentProgressBinding biding; + @Inject PreferenceManager preferenceManager; @Inject TestProgressRepository testProgressRepository; - @BindView(R.id.progress_layout) - FrameLayout progress_layout; - @BindView(R.id.progress) - ProgressBar progress; - @BindView(R.id.running) - TextView running; - @BindView(R.id.name) - TextView name; public ProgressFragment() { // Required empty public constructor @@ -62,24 +47,18 @@ public void onCreate(Bundle savedInstanceState) { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_progress, container, false); - ButterKnife.bind(this, v); + biding = FragmentProgressBinding.inflate(inflater, container, false); ((Application) getActivity().getApplication()).getFragmentComponent().inject(this); - v.setOnTouchListener(new View.OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - if(event.getAction() == MotionEvent.ACTION_DOWN){ - Intent intent = new Intent(getContext(), RunningActivity.class); - ActivityCompat.startActivity(getActivity(), intent, null); - } - return true; - } + biding.getRoot().setOnClickListener(v -> { + Intent intent = new Intent(getContext(), RunningActivity.class); + ActivityCompat.startActivity(getActivity(), intent, null); }); testProgressRepository.getProgress().observe(getViewLifecycleOwner(),progressValue -> { if (progressValue!=null) { - progress.setProgress(progressValue); + biding.progress.setProgress(progressValue); } }); - return v; + return biding.getRoot(); } @Override @@ -97,10 +76,10 @@ public void bindTestService() { if (activity!=null && ((Application)activity.getApplication()).isTestRunning()) { Intent intent = new Intent(getActivity(), RunTestService.class); getActivity().bindService(intent, receiver, Context.BIND_AUTO_CREATE); - progress_layout.setVisibility(View.VISIBLE); + biding.progressLayout.setVisibility(View.VISIBLE); } else - progress_layout.setVisibility(View.GONE); + biding.progressLayout.setVisibility(View.GONE); } private void updateUI(RunTestService service){ @@ -109,15 +88,15 @@ private void updateUI(RunTestService service){ Integer progressLevel = testProgressRepository.getProgress().getValue(); if (progressLevel != null) { - progress.setProgress(progressLevel); + biding.progress.setProgress(progressLevel); } else { - progress.setIndeterminate(true); + biding.progress.setIndeterminate(true); } if (service != null && service.task != null){ if (service.task.currentSuite != null) - progress.setMax(service.task.getMax(preferenceManager)); + biding.progress.setMax(service.task.getMax(preferenceManager)); if (service.task.currentTest != null) - name.setText(getString(service.task.currentTest.getLabelResId())); + biding.name.setText(getString(service.task.currentTest.getLabelResId())); } } } @@ -146,15 +125,15 @@ public void onStart(RunTestService service) { @Override public void onRun(String value) { - name.setText(value); + biding.name.setText(value); } @Override public void onProgress(int state, double eta) { - if (progress.isIndeterminate()) + if (biding.progress.isIndeterminate()) updateUI(receiver.service); - progress.setIndeterminate(false); - progress.setProgress(state); + biding.progress.setIndeterminate(false); + biding.progress.setProgress(state); } @Override @@ -169,17 +148,17 @@ public void onError(String value) { @Override public void onUrl() { - progress.setIndeterminate(false); + biding.progress.setIndeterminate(false); } @Override public void onInterrupt() { - running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); + biding.running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); } @Override public void onEnd(Context context) { - progress_layout.setVisibility(View.GONE); + biding.progressLayout.setVisibility(View.GONE); } } } \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java index c0835739d..8b881c25e 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java @@ -3,30 +3,21 @@ import android.app.ProgressDialog; import android.content.DialogInterface; import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Spinner; -import android.widget.TextView; - +import android.view.*; +import android.widget.AdapterView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - import com.google.android.material.snackbar.Snackbar; import com.raizlabs.android.dbflow.sql.language.Method; import com.raizlabs.android.dbflow.sql.language.SQLite; - +import localhost.toolkit.app.fragment.ConfirmDialogFragment; +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerAdapter; +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.activity.AbstractActivity; import org.openobservatory.ooniprobe.activity.ResultDetailActivity; @@ -34,60 +25,25 @@ import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.ResubmitTask; +import org.openobservatory.ooniprobe.databinding.FragmentResultListBinding; import org.openobservatory.ooniprobe.domain.GetResults; import org.openobservatory.ooniprobe.domain.MeasurementsManager; import org.openobservatory.ooniprobe.domain.models.DatedResults; -import org.openobservatory.ooniprobe.item.CircumventionItem; -import org.openobservatory.ooniprobe.item.DateItem; -import org.openobservatory.ooniprobe.item.ExperimentalItem; -import org.openobservatory.ooniprobe.item.FailedItem; -import org.openobservatory.ooniprobe.item.InstantMessagingItem; -import org.openobservatory.ooniprobe.item.MiddleboxesItem; -import org.openobservatory.ooniprobe.item.PerformanceItem; -import org.openobservatory.ooniprobe.item.WebsiteItem; +import org.openobservatory.ooniprobe.item.*; import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.model.database.Result_Table; -import org.openobservatory.ooniprobe.test.suite.CircumventionSuite; -import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite; -import org.openobservatory.ooniprobe.test.suite.InstantMessagingSuite; -import org.openobservatory.ooniprobe.test.suite.MiddleBoxesSuite; -import org.openobservatory.ooniprobe.test.suite.PerformanceSuite; -import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import org.openobservatory.ooniprobe.test.suite.*; +import javax.inject.Inject; import java.io.Serializable; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnItemSelected; -import localhost.toolkit.app.fragment.ConfirmDialogFragment; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerAdapter; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class ResultListFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener, ConfirmDialogFragment.OnConfirmedListener { - @BindView(R.id.coordinatorLayout) - CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar) - Toolbar toolbar; - @BindView(R.id.tests) - TextView tests; - @BindView(R.id.networks) - TextView networks; - @BindView(R.id.upload) - TextView upload; - @BindView(R.id.download) - TextView download; - @BindView(R.id.filterTests) - Spinner filterTests; - @BindView(R.id.recycler) - RecyclerView recycler; - @BindView(R.id.emptyState) - TextView emptyState; + private FragmentResultListBinding binding; + private ArrayList items; private HeterogeneousRecyclerAdapter adapter; private boolean refresh; @@ -105,20 +61,32 @@ public class ResultListFragment extends Fragment implements View.OnClickListener @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_result_list, container, false); - ButterKnife.bind(this, v); + binding = FragmentResultListBinding.inflate(inflater, container, false); ((Application) getActivity().getApplication()).getFragmentComponent().inject(this); - ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); + ((AppCompatActivity) getActivity()).setSupportActionBar(binding.toolbar); setHasOptionsMenu(true); getActivity().setTitle(R.string.TestResults_Overview_Title); reloadHeader(); LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); - recycler.setLayoutManager(layoutManager); - recycler.addItemDecoration(new DividerItemDecoration(getActivity(), layoutManager.getOrientation())); + binding.recycler.setLayoutManager(layoutManager); + binding.recycler.addItemDecoration(new DividerItemDecoration(getActivity(), layoutManager.getOrientation())); items = new ArrayList<>(); adapter = new HeterogeneousRecyclerAdapter<>(getActivity(), items); - recycler.setAdapter(adapter); - snackbar = Snackbar.make(coordinatorLayout, R.string.Snackbar_ResultsSomeNotUploaded_Text, Snackbar.LENGTH_INDEFINITE) + binding.recycler.setAdapter(adapter); + + binding.filterTests.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + queryList(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + queryList(); + } + }); + + snackbar = Snackbar.make(binding.coordinatorLayout, R.string.Snackbar_ResultsSomeNotUploaded_Text, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.Snackbar_ResultsSomeNotUploaded_UploadAll, v1 -> new ConfirmDialogFragment.Builder() .withExtra(R.string.Modal_ResultsNotUploaded_Title) @@ -127,14 +95,14 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c .withPositiveButton(getString(R.string.Modal_ResultsNotUploaded_Button_Upload)) .build().show(getChildFragmentManager(), null) ); - return v; + return binding.getRoot(); } public void reloadHeader() { - tests.setText(getString(R.string.d, SQLite.selectCountOf().from(Result.class).longValue())); - networks.setText(getString(R.string.d, SQLite.selectCountOf().from(Network.class).longValue())); - upload.setText(Result.readableFileSize(SQLite.select(Method.sum(Result_Table.data_usage_up)).from(Result.class).longValue())); - download.setText(Result.readableFileSize(SQLite.select(Method.sum(Result_Table.data_usage_down)).from(Result.class).longValue())); + binding.tests.setText(getString(R.string.d, SQLite.selectCountOf().from(Result.class).longValue())); + binding.networks.setText(getString(R.string.d, SQLite.selectCountOf().from(Network.class).longValue())); + binding.upload.setText(Result.readableFileSize(SQLite.select(Method.sum(Result_Table.data_usage_up)).from(Result.class).longValue())); + binding.download.setText(Result.readableFileSize(SQLite.select(Method.sum(Result_Table.data_usage_down)).from(Result.class).longValue())); } @Override @@ -173,7 +141,6 @@ public boolean onOptionsItemSelected(MenuItem item) { } } - @OnItemSelected(R.id.filterTests) void queryList() { if (measurementsManager.hasUploadables()) { snackbar.show(); @@ -183,15 +150,15 @@ void queryList() { items.clear(); - String filter = getResources().getStringArray(R.array.filterTestValues)[filterTests.getSelectedItemPosition()]; + String filter = getResources().getStringArray(R.array.filterTestValues)[binding.filterTests.getSelectedItemPosition()]; List list = getResults.getGroupedByMonth(filter); if (list.isEmpty()) { - emptyState.setVisibility(View.VISIBLE); - recycler.setVisibility(View.GONE); + binding.emptyState.setVisibility(View.VISIBLE); + binding.recycler.setVisibility(View.GONE); } else { - emptyState.setVisibility(View.GONE); - recycler.setVisibility(View.VISIBLE); + binding.emptyState.setVisibility(View.GONE); + binding.recycler.setVisibility(View.VISIBLE); for (DatedResults group : list) { items.add(new DateItem(group.getGroupedDate())); for (Result result : group.getResultsList()) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/DashFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/DashFragment.java index d5f29b7e9..ed6d8c58d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/DashFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/DashFragment.java @@ -5,22 +5,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementDashBinding; import org.openobservatory.ooniprobe.model.database.Measurement; -import butterknife.BindView; -import butterknife.ButterKnife; - public class DashFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.medianBitrate) TextView medianBitrate; - @BindView(R.id.playoutDelay) TextView playoutDelay; public static DashFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -30,14 +23,15 @@ public static DashFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_dash, container, false); - ButterKnife.bind(this, v); - medianBitrate.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getMedianBitrate(getActivity()), getString(measurement.getTestKeys().getMedianBitrateUnit())))); - playoutDelay.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getPlayoutDelay(getActivity()), "s"))); - return v; + FragmentMeasurementDashBinding binding = FragmentMeasurementDashBinding.inflate(inflater,container,false); + binding.medianBitrate.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getMedianBitrate(getActivity()), getString(measurement.getTestKeys().getMedianBitrateUnit())))); + binding.playoutDelay.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getPlayoutDelay(getActivity()), "s"))); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FacebookMessengerFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FacebookMessengerFragment.java index 4792e9963..b3613c949 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FacebookMessengerFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FacebookMessengerFragment.java @@ -4,25 +4,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementFacebookmessengerBinding; import org.openobservatory.ooniprobe.model.database.Measurement; -import butterknife.BindView; -import butterknife.ButterKnife; - public class FacebookMessengerFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.tcp) TextView tcp; - @BindView(R.id.dns) TextView dns; - @BindView(R.id.desc) TextView desc; - public static FacebookMessengerFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); args.putSerializable(MEASUREMENT, measurement); @@ -31,19 +22,20 @@ public static FacebookMessengerFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_facebookmessenger, container, false); - ButterKnife.bind(this, v); - desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_FacebookMessenger_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_FacebookMessenger_Reachable_Content_Paragraph); - dns.setText(measurement.getTestKeys().getFacebookMessengerDns()); + FragmentMeasurementFacebookmessengerBinding binding = FragmentMeasurementFacebookmessengerBinding.inflate(inflater,container,false); + binding.desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_FacebookMessenger_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_FacebookMessenger_Reachable_Content_Paragraph); + binding.dns.setText(measurement.getTestKeys().getFacebookMessengerDns()); if (Boolean.TRUE.equals(measurement.getTestKeys().facebook_dns_blocking)) - dns.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); - tcp.setText(measurement.getTestKeys().getFacebookMessengerTcp()); + binding.dns.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); + binding.tcp.setText(measurement.getTestKeys().getFacebookMessengerTcp()); if (Boolean.TRUE.equals(measurement.getTestKeys().facebook_tcp_blocking)) - tcp.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); - return v; + binding.tcp.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FailedFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FailedFragment.java index 6b04f8c92..ba9f6f98a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FailedFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/FailedFragment.java @@ -37,13 +37,15 @@ public static FailedFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { binding = FragmentMeasurementFailedBinding.inflate(inflater,container,false); binding.tryAgain.setOnClickListener(this::tryAgainClick); return binding.getRoot(); } - void tryAgainClick(View view) { + void tryAgainClick(View view) { assert getArguments() != null; Measurement failedMeasurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert failedMeasurement != null; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderNdtFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderNdtFragment.java index 04bab8f95..2467cf99e 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderNdtFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderNdtFragment.java @@ -5,24 +5,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementHeaderNdtBinding; import org.openobservatory.ooniprobe.model.database.Measurement; -import butterknife.BindView; -import butterknife.ButterKnife; - public class HeaderNdtFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.download) TextView download; - @BindView(R.id.upload) TextView upload; - @BindView(R.id.ping) TextView ping; - @BindView(R.id.server) TextView server; public static HeaderNdtFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -32,16 +23,17 @@ public static HeaderNdtFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_header_ndt, container, false); - ButterKnife.bind(this, v); - download.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getDownload(getActivity()), getString(measurement.getTestKeys().getDownloadUnit())))); - upload.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getUpload(getActivity()), getString(measurement.getTestKeys().getUploadUnit())))); - ping.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getPing(getActivity()), "ms"))); - server.setText(measurement.getTestKeys().getServerDetails(getActivity())); - return v; + FragmentMeasurementHeaderNdtBinding binding = FragmentMeasurementHeaderNdtBinding.inflate(inflater,container,false); + binding.download.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getDownload(getActivity()), getString(measurement.getTestKeys().getDownloadUnit())))); + binding.upload.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getUpload(getActivity()), getString(measurement.getTestKeys().getUploadUnit())))); + binding.ping.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getPing(getActivity()), "ms"))); + binding.server.setText(measurement.getTestKeys().getServerDetails(getActivity())); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderOutcomeFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderOutcomeFragment.java index 164b9361c..52af50b58 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderOutcomeFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HeaderOutcomeFragment.java @@ -5,21 +5,14 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - -import org.openobservatory.ooniprobe.R; - -import butterknife.BindView; -import butterknife.ButterKnife; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementHeaderOutcomeBinding; public class HeaderOutcomeFragment extends Fragment { public static final String ICON_RES = "iconRes"; private static final String DESC = "desc"; - @BindView(R.id.outcome) TextView outcome; public static HeaderOutcomeFragment newInstance(Integer iconRes, String desc) { Bundle args = new Bundle(); @@ -31,13 +24,14 @@ public static HeaderOutcomeFragment newInstance(Integer iconRes, String desc) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { assert getArguments() != null; - View v = inflater.inflate(R.layout.fragment_measurement_header_outcome, container, false); - ButterKnife.bind(this, v); - outcome.setText(Html.fromHtml(getArguments().getString(DESC))); + FragmentMeasurementHeaderOutcomeBinding binding = FragmentMeasurementHeaderOutcomeBinding.inflate(inflater,container,false); + binding.outcome.setText(Html.fromHtml(getArguments().getString(DESC))); if (getArguments().containsKey(ICON_RES)) - outcome.setCompoundDrawablesRelativeWithIntrinsicBounds(0, getArguments().getInt(ICON_RES), 0, 0); - return v; + binding.outcome.setCompoundDrawablesRelativeWithIntrinsicBounds(0, getArguments().getInt(ICON_RES), 0, 0); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpHeaderFieldManipulationFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpHeaderFieldManipulationFragment.java index 7dccf0034..aca7b2cd6 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpHeaderFieldManipulationFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpHeaderFieldManipulationFragment.java @@ -4,21 +4,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementHttpheaderfieldmanipulationBinding; import org.openobservatory.ooniprobe.model.database.Measurement; -import butterknife.BindView; -import butterknife.ButterKnife; - public class HttpHeaderFieldManipulationFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.desc) TextView desc; public static HttpHeaderFieldManipulationFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -28,13 +22,14 @@ public static HttpHeaderFieldManipulationFragment newInstance(Measurement measur return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_httpheaderfieldmanipulation, container, false); - ButterKnife.bind(this, v); - desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_Middleboxes_HTTPHeaderFieldManipulation_Found_Content_Paragraph : R.string.TestResults_Details_Middleboxes_HTTPHeaderFieldManipulation_NotFound_Content_Paragraph); - return v; + FragmentMeasurementHttpheaderfieldmanipulationBinding binding = FragmentMeasurementHttpheaderfieldmanipulationBinding.inflate(inflater,container,false); + binding.desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_Middleboxes_HTTPHeaderFieldManipulation_Found_Content_Paragraph : R.string.TestResults_Details_Middleboxes_HTTPHeaderFieldManipulation_NotFound_Content_Paragraph); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpInvalidRequestLineFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpInvalidRequestLineFragment.java index 0c2135abf..aa3015b3e 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpInvalidRequestLineFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/HttpInvalidRequestLineFragment.java @@ -4,21 +4,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementHttpinvalidrequestlineBinding; import org.openobservatory.ooniprobe.model.database.Measurement; -import butterknife.BindView; -import butterknife.ButterKnife; - public class HttpInvalidRequestLineFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.desc) TextView desc; public static HttpInvalidRequestLineFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -28,13 +22,14 @@ public static HttpInvalidRequestLineFragment newInstance(Measurement measurement return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_httpinvalidrequestline, container, false); - ButterKnife.bind(this, v); - desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_Middleboxes_HTTPInvalidRequestLine_Found_Content_Paragraph : R.string.TestResults_Details_Middleboxes_HTTPInvalidRequestLine_NotFound_Content_Paragraph); - return v; + FragmentMeasurementHttpinvalidrequestlineBinding biding = FragmentMeasurementHttpinvalidrequestlineBinding.inflate(inflater,container,false); + biding.desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_Middleboxes_HTTPInvalidRequestLine_Found_Content_Paragraph : R.string.TestResults_Details_Middleboxes_HTTPInvalidRequestLine_NotFound_Content_Paragraph); + return biding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/NdtFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/NdtFragment.java index 16596a393..1223c562f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/NdtFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/NdtFragment.java @@ -5,24 +5,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementNdtBinding; import org.openobservatory.ooniprobe.model.database.Measurement; -import butterknife.BindView; -import butterknife.ButterKnife; - public class NdtFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.packetLoss) TextView packetLoss; - @BindView(R.id.averagePing) TextView averagePing; - @BindView(R.id.maxPing) TextView maxPing; - @BindView(R.id.mss) TextView mss; public static NdtFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -36,12 +27,11 @@ public static NdtFragment newInstance(Measurement measurement) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_ndt, container, false); - ButterKnife.bind(this, v); - packetLoss.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getPacketLoss(getActivity()), "%"))); - averagePing.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getAveragePing(getActivity()), "ms"))); - maxPing.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getMaxPing(getActivity()), "ms"))); - mss.setText(measurement.getTestKeys().getMSS(getActivity())); - return v; + FragmentMeasurementNdtBinding binding = FragmentMeasurementNdtBinding.inflate(inflater,container,false); + binding.packetLoss.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getPacketLoss(getActivity()), "%"))); + binding.averagePing.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getAveragePing(getActivity()), "ms"))); + binding.maxPing.setText(Html.fromHtml(getString(R.string.bigNormal, measurement.getTestKeys().getMaxPing(getActivity()), "ms"))); + binding.mss.setText(measurement.getTestKeys().getMSS(getActivity())); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/PsiphonFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/PsiphonFragment.java index 33755b2fc..ae697cff3 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/PsiphonFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/PsiphonFragment.java @@ -4,23 +4,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementPsiphonBinding; import org.openobservatory.ooniprobe.model.database.Measurement; - -import butterknife.BindView; -import butterknife.ButterKnife; import ru.noties.markwon.Markwon; public class PsiphonFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.bootstrap) TextView bootstrap; - @BindView(R.id.desc) TextView desc; public static PsiphonFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -34,14 +27,13 @@ public static PsiphonFragment newInstance(Measurement measurement) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_psiphon, container, false); - ButterKnife.bind(this, v); - Markwon.setMarkdown(desc, + FragmentMeasurementPsiphonBinding binding = FragmentMeasurementPsiphonBinding.inflate(inflater,container,false); + Markwon.setMarkdown(binding.desc, measurement.is_anomaly ? getString(R.string.TestResults_Details_Circumvention_Psiphon_Blocked_Content_Paragraph) : getString(R.string.TestResults_Details_Circumvention_Psiphon_Reachable_Content_Paragraph) ); - bootstrap.setText(measurement.getTestKeys().getBootstrapTime(getActivity())); - return v; + binding.bootstrap.setText(measurement.getTestKeys().getBootstrapTime(getActivity())); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/RiseupVPNFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/RiseupVPNFragment.java index c0bddd732..83670bd5e 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/RiseupVPNFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/RiseupVPNFragment.java @@ -4,25 +4,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementRiseupvpnBinding; import org.openobservatory.ooniprobe.model.database.Measurement; - -import butterknife.BindView; -import butterknife.ButterKnife; import ru.noties.markwon.Markwon; public class RiseupVPNFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.bootstrap_value) TextView bootstrap_value; - @BindView(R.id.openvpn_value) TextView openvpn_value; - @BindView(R.id.bridges_value) TextView bridges_value; - @BindView(R.id.desc) TextView desc; public static RiseupVPNFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -36,16 +27,15 @@ public static RiseupVPNFragment newInstance(Measurement measurement) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_riseupvpn, container, false); - ButterKnife.bind(this, v); - Markwon.setMarkdown(desc, + FragmentMeasurementRiseupvpnBinding binding = FragmentMeasurementRiseupvpnBinding.inflate(inflater,container,false); + Markwon.setMarkdown(binding.desc, measurement.is_anomaly ? getString(R.string.TestResults_Details_Circumvention_RiseupVPN_Blocked_Content_Paragraph) : getString(R.string.TestResults_Details_Circumvention_RiseupVPN_Reachable_Content_Paragraph) ); - bootstrap_value.setText(measurement.getTestKeys().getRiseupVPNApiStatus()); - openvpn_value.setText(measurement.getTestKeys().getRiseupVPNOpenvpnGatewayStatus(getContext())); - bridges_value.setText(measurement.getTestKeys().getRiseupVPNBridgedGatewayStatus(getContext())); - return v; + binding.bootstrapValue.setText(measurement.getTestKeys().getRiseupVPNApiStatus()); + binding.openvpnValue.setText(measurement.getTestKeys().getRiseupVPNOpenvpnGatewayStatus(getContext())); + binding.bridgesValue.setText(measurement.getTestKeys().getRiseupVPNBridgedGatewayStatus(getContext())); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/SignalFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/SignalFragment.java index 869345136..aa395e3d9 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/SignalFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/SignalFragment.java @@ -4,21 +4,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementSignalBinding; import org.openobservatory.ooniprobe.model.database.Measurement; -import butterknife.BindView; -import butterknife.ButterKnife; - public class SignalFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.desc) TextView desc; public static SignalFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -32,9 +26,8 @@ public static SignalFragment newInstance(Measurement measurement) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_signal, container, false); - ButterKnife.bind(this, v); - desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_Signal_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_Signal_Reachable_Content_Paragraph); - return v; + FragmentMeasurementSignalBinding binding = FragmentMeasurementSignalBinding.inflate(inflater,container,false); + binding.desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_Signal_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_Signal_Reachable_Content_Paragraph); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TelegramFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TelegramFragment.java index da689104a..3c1e8920e 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TelegramFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TelegramFragment.java @@ -4,25 +4,17 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementTelegramBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.jsonresult.TestKeys; -import butterknife.BindView; -import butterknife.ButterKnife; - public class TelegramFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.application) TextView application; - @BindView(R.id.webApp) TextView webApp; - @BindView(R.id.desc) TextView desc; public static TelegramFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -32,19 +24,20 @@ public static TelegramFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_telegram, container, false); - ButterKnife.bind(this, v); - desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_Telegram_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_Telegram_Reachable_Content_Paragraph); - application.setText(measurement.getTestKeys().getTelegramEndpointStatus()); + FragmentMeasurementTelegramBinding binding = FragmentMeasurementTelegramBinding.inflate(inflater,container,false); + binding.desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_Telegram_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_Telegram_Reachable_Content_Paragraph); + binding.application.setText(measurement.getTestKeys().getTelegramEndpointStatus()); if (Boolean.TRUE.equals(measurement.getTestKeys().telegram_http_blocking) || Boolean.TRUE.equals(measurement.getTestKeys().telegram_tcp_blocking)) - application.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); - webApp.setText(measurement.getTestKeys().getTelegramWebStatus()); + binding.application.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); + binding.webApp.setText(measurement.getTestKeys().getTelegramWebStatus()); if (TestKeys.BLOCKED.equals(measurement.getTestKeys().telegram_web_status)) - webApp.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); - return v; + binding.webApp.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TorFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TorFragment.java index 4140994f6..3b47b9dcd 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TorFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/TorFragment.java @@ -4,24 +4,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementTorBinding; import org.openobservatory.ooniprobe.model.database.Measurement; - -import butterknife.BindView; -import butterknife.ButterKnife; import ru.noties.markwon.Markwon; public class TorFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.bridges) TextView bridges; - @BindView(R.id.authorities) TextView authorities; - @BindView(R.id.desc) TextView desc; public static TorFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -31,19 +23,20 @@ public static TorFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_tor, container, false); - ButterKnife.bind(this, v); - Markwon.setMarkdown(desc, + FragmentMeasurementTorBinding binding = FragmentMeasurementTorBinding.inflate(inflater,container,false); + Markwon.setMarkdown(binding.desc, measurement.is_anomaly ? getString(R.string.TestResults_Details_Circumvention_Tor_Blocked_Content_Paragraph) : getString(R.string.TestResults_Details_Circumvention_Tor_Reachable_Content_Paragraph) ); - bridges.setText(measurement.getTestKeys().getBridges(getActivity())); - authorities.setText(measurement.getTestKeys().getAuthorities(getActivity())); - return v; + binding.bridges.setText(measurement.getTestKeys().getBridges(getActivity())); + binding.authorities.setText(measurement.getTestKeys().getAuthorities(getActivity())); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WebConnectivityFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WebConnectivityFragment.java index 5f0fb32cf..e39131b45 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WebConnectivityFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WebConnectivityFragment.java @@ -4,22 +4,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementWebconnectivityBinding; import org.openobservatory.ooniprobe.model.database.Measurement; - -import butterknife.BindView; -import butterknife.ButterKnife; import ru.noties.markwon.Markwon; public class WebConnectivityFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.desc) TextView desc; public static WebConnectivityFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -29,16 +23,17 @@ public static WebConnectivityFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_webconnectivity, container, false); - ButterKnife.bind(this, v); + FragmentMeasurementWebconnectivityBinding binding = FragmentMeasurementWebconnectivityBinding.inflate(inflater,container,false); if (measurement.is_anomaly) - Markwon.setMarkdown(desc, getString(R.string.TestResults_Details_Websites_LikelyBlocked_Content_Paragraph, measurement.url.url, getString(measurement.getTestKeys().getWebsiteBlocking()))); + Markwon.setMarkdown(binding.desc, getString(R.string.TestResults_Details_Websites_LikelyBlocked_Content_Paragraph, measurement.url.url, getString(measurement.getTestKeys().getWebsiteBlocking()))); else - Markwon.setMarkdown(desc, getString(R.string.TestResults_Details_Websites_Reachable_Content_Paragraph, measurement.url.url)); - return v; + Markwon.setMarkdown(binding.desc, getString(R.string.TestResults_Details_Websites_Reachable_Content_Paragraph, measurement.url.url)); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WhatsappFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WhatsappFragment.java index 74cf5ce4d..e8e319940 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WhatsappFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/measurement/WhatsappFragment.java @@ -4,26 +4,17 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentMeasurementWhatsappBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.jsonresult.TestKeys; -import butterknife.BindView; -import butterknife.ButterKnife; - public class WhatsappFragment extends Fragment { private static final String MEASUREMENT = "measurement"; - @BindView(R.id.desc) TextView desc; - @BindView(R.id.application) TextView application; - @BindView(R.id.webApp) TextView webApp; - @BindView(R.id.registrations) TextView registrations; public static WhatsappFragment newInstance(Measurement measurement) { Bundle args = new Bundle(); @@ -33,22 +24,23 @@ public static WhatsappFragment newInstance(Measurement measurement) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; Measurement measurement = (Measurement) getArguments().getSerializable(MEASUREMENT); assert measurement != null; - View v = inflater.inflate(R.layout.fragment_measurement_whatsapp, container, false); - ButterKnife.bind(this, v); - desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_WhatsApp_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_WhatsApp_Reachable_Content_Paragraph); - application.setText(measurement.getTestKeys().getWhatsappEndpointStatus()); + FragmentMeasurementWhatsappBinding binding = FragmentMeasurementWhatsappBinding.inflate(inflater,container,false); + binding.desc.setText(measurement.is_anomaly ? R.string.TestResults_Details_InstantMessaging_WhatsApp_LikelyBlocked_Content_Paragraph : R.string.TestResults_Details_InstantMessaging_WhatsApp_Reachable_Content_Paragraph); + binding.application.setText(measurement.getTestKeys().getWhatsappEndpointStatus()); if (TestKeys.BLOCKED.equals(measurement.getTestKeys().whatsapp_endpoints_status)) - application.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); - webApp.setText(measurement.getTestKeys().getWhatsappWebStatus()); + binding.application.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); + binding.webApp.setText(measurement.getTestKeys().getWhatsappWebStatus()); if (TestKeys.BLOCKED.equals(measurement.getTestKeys().whatsapp_web_status)) - webApp.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); - registrations.setText(measurement.getTestKeys().getWhatsappRegistrationStatus()); + binding.webApp.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); + binding.registrations.setText(measurement.getTestKeys().getWhatsappRegistrationStatus()); if (TestKeys.BLOCKED.equals(measurement.getTestKeys().registration_server_status)) - registrations.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); - return v; + binding.registrations.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_yellow9)); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding1Fragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding1Fragment.java index ddc203fbb..54382527a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding1Fragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding1Fragment.java @@ -4,24 +4,21 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - -import org.openobservatory.ooniprobe.R; - -import butterknife.ButterKnife; -import butterknife.OnClick; +import org.openobservatory.ooniprobe.databinding.FragmentOnboarding1Binding; public class Onboarding1Fragment extends Fragment { - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_onboarding_1, container, false); - ButterKnife.bind(this, v); - return v; + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + FragmentOnboarding1Binding binding = FragmentOnboarding1Binding.inflate(inflater, container, false); + binding.master.setOnClickListener(v -> masterClick()); + return binding.getRoot(); } - @OnClick(R.id.master) void masterClick() { + void masterClick() { getParentFragmentManager().beginTransaction().replace(android.R.id.content, new Onboarding2Fragment()).commit(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding2Fragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding2Fragment.java index 663da5a4c..fddbc294b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding2Fragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding2Fragment.java @@ -6,41 +6,36 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; +import org.openobservatory.ooniprobe.databinding.FragmentOnboarding2Binding; public class Onboarding2Fragment extends Fragment implements OnboardingDialogPopquizFragment.OnboardingPopquizInterface, OnboardingDialogWarningFragment.OnboardingWarningInterface { - @BindView(R.id.bullet1) TextView bullet1; - @BindView(R.id.bullet2) TextView bullet2; - @BindView(R.id.bullet3) TextView bullet3; - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_onboarding_2, container, false); - ButterKnife.bind(this, v); - bullet1.setText(getString(R.string.bullet, getString(R.string.Onboarding_ThingsToKnow_Bullet_1))); - bullet2.setText(getString(R.string.bullet, getString(R.string.Onboarding_ThingsToKnow_Bullet_2))); - bullet3.setText(getString(R.string.bullet, getString(R.string.Onboarding_ThingsToKnow_Bullet_3))); - return v; + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + FragmentOnboarding2Binding binding = FragmentOnboarding2Binding.inflate(inflater, container, false); + binding.bullet1.setText(getString(R.string.bullet, getString(R.string.Onboarding_ThingsToKnow_Bullet_1))); + binding.bullet2.setText(getString(R.string.bullet, getString(R.string.Onboarding_ThingsToKnow_Bullet_2))); + binding.bullet3.setText(getString(R.string.bullet, getString(R.string.Onboarding_ThingsToKnow_Bullet_3))); + binding.master.setOnClickListener(v -> masterClick()); + binding.slave.setOnClickListener(v -> slaveClick()); + return binding.getRoot(); } - @OnClick(R.id.master) void masterClick() { + void masterClick() { OnboardingDialogPopquizFragment.newInstance(R.string.Onboarding_PopQuiz_1_Title, R.string.Onboarding_PopQuiz_1_Question).show(getChildFragmentManager(), null); } - @OnClick(R.id.slave) void slaveClick() { + void slaveClick() { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://ooni.io/about/risks/"))); } - @Override public void onPopquizResult(int questionResId, boolean positive) { + @Override + public void onPopquizResult(int questionResId, boolean positive) { if (questionResId == R.string.Onboarding_PopQuiz_1_Question) { if (positive) OnboardingDialogPopquizFragment.newInstance(R.string.Onboarding_PopQuiz_2_Title, R.string.Onboarding_PopQuiz_2_Question).show(getChildFragmentManager(), null); @@ -54,7 +49,8 @@ public class Onboarding2Fragment extends Fragment implements OnboardingDialogPop } } - @Override public void onWarningResult(int questionResId) { + @Override + public void onWarningResult(int questionResId) { if (questionResId == R.string.Onboarding_PopQuiz_1_Wrong_Paragraph) OnboardingDialogPopquizFragment.newInstance(R.string.Onboarding_PopQuiz_2_Title, R.string.Onboarding_PopQuiz_2_Question).show(getChildFragmentManager(), null); else if (questionResId == R.string.Onboarding_PopQuiz_2_Wrong_Paragraph) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding3Fragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding3Fragment.java index cc649e834..005204e37 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding3Fragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/Onboarding3Fragment.java @@ -4,48 +4,42 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.activity.MainActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.ThirdPartyServices; import org.openobservatory.ooniprobe.common.service.ServiceUtil; +import org.openobservatory.ooniprobe.databinding.FragmentOnboarding3Binding; +import ru.noties.markwon.Markwon; import javax.inject.Inject; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import ru.noties.markwon.Markwon; - public class Onboarding3Fragment extends Fragment { @Inject PreferenceManager preferenceManager; - @BindView(R.id.bullet1) TextView bullet1; - @BindView(R.id.bullet2) TextView bullet2; - @BindView(R.id.bullet3) TextView bullet3; - @BindView(R.id.paragraph) TextView paragraph; - - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { ((Application) getActivity().getApplication()).getFragmentComponent().inject(this); - View v = inflater.inflate(R.layout.fragment_onboarding_3, container, false); - ButterKnife.bind(this, v); - bullet1.setText(getString(R.string.bullet, getString(R.string.Onboarding_DefaultSettings_Bullet_1))); - bullet2.setText(getString(R.string.bullet, getString(R.string.Onboarding_DefaultSettings_Bullet_2))); - bullet3.setText(getString(R.string.bullet, getString(R.string.Onboarding_DefaultSettings_Bullet_3))); - Markwon.setMarkdown(paragraph, getString(R.string.Onboarding_DefaultSettings_Paragraph)); - return v; + FragmentOnboarding3Binding binding = FragmentOnboarding3Binding.inflate(inflater, container, false); + binding.bullet1.setText(getString(R.string.bullet, getString(R.string.Onboarding_DefaultSettings_Bullet_1))); + binding.bullet2.setText(getString(R.string.bullet, getString(R.string.Onboarding_DefaultSettings_Bullet_2))); + binding.bullet3.setText(getString(R.string.bullet, getString(R.string.Onboarding_DefaultSettings_Bullet_3))); + Markwon.setMarkdown(binding.paragraph, getString(R.string.Onboarding_DefaultSettings_Paragraph)); + + binding.master.setOnClickListener(v -> masterClick()); + binding.slave.setOnClickListener(v -> slaveClick()); + + return binding.getRoot(); } - @OnClick(R.id.master) void masterClick() { + void masterClick() { preferenceManager.setShowOnboarding(false); ThirdPartyServices.reloadConsents((Application) getActivity().getApplication()); startAutoTestIfNeeded(); @@ -53,7 +47,7 @@ public class Onboarding3Fragment extends Fragment { getActivity().finish(); } - @OnClick(R.id.slave) void slaveClick() { + void slaveClick() { preferenceManager.setShowOnboarding(false); startAutoTestIfNeeded(); startActivity(MainActivity.newIntent(getActivity(), R.id.settings)); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingAutoTestFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingAutoTestFragment.java index 38f520820..01ebce218 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingAutoTestFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingAutoTestFragment.java @@ -10,42 +10,39 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - +import localhost.toolkit.app.fragment.ConfirmDialogFragment; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.ThirdPartyServices; - -import java.io.Serializable; +import org.openobservatory.ooniprobe.databinding.FragmentOnboardingAutotestBinding; import javax.inject.Inject; - -import butterknife.ButterKnife; -import butterknife.OnClick; -import localhost.toolkit.app.fragment.ConfirmDialogFragment; +import java.io.Serializable; public class OnboardingAutoTestFragment extends Fragment implements ConfirmDialogFragment.OnConfirmedListener { @Inject PreferenceManager preferenceManager; public static final String BATTERY_DIALOG = "battery_optimization"; @Nullable - @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { ((Application) getActivity().getApplication()).getFragmentComponent().inject(this); - View v = inflater.inflate(R.layout.fragment_onboarding_autotest, container, false); - ButterKnife.bind(this, v); - return v; + FragmentOnboardingAutotestBinding binding = FragmentOnboardingAutotestBinding.inflate(inflater, container, false); + binding.master.setOnClickListener(v -> masterClick()); + binding.slave.setOnClickListener(v -> slaveClick()); + return binding.getRoot(); } - @OnClick(R.id.master) void masterClick() { + void masterClick() { enableAutoTest(); } - @OnClick(R.id.slave) void slaveClick() { + void slaveClick() { next(); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingCrashFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingCrashFragment.java index d3ece3295..1c4c97b94 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingCrashFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingCrashFragment.java @@ -4,32 +4,29 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - -import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.ThirdPartyServices; - -import butterknife.ButterKnife; -import butterknife.OnClick; +import org.openobservatory.ooniprobe.databinding.FragmentOnboardingCrashBinding; public class OnboardingCrashFragment extends Fragment { @Nullable - @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_onboarding_crash, container, false); - ButterKnife.bind(this, v); - return v; + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + FragmentOnboardingCrashBinding binding = FragmentOnboardingCrashBinding.inflate(inflater, container, false); + binding.master.setOnClickListener(v -> masterClick()); + binding.slave.setOnClickListener(v -> slaveClick()); + return binding.getRoot(); } - @OnClick(R.id.master) void masterClick() { + void masterClick() { ThirdPartyServices.acceptCrash((Application) getActivity().getApplication()); getParentFragmentManager().beginTransaction().replace(android.R.id.content, new Onboarding3Fragment()).commit(); } - @OnClick(R.id.slave) void slaveClick() { + void slaveClick() { getParentFragmentManager().beginTransaction().replace(android.R.id.content, new Onboarding3Fragment()).commit(); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogPopquizFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogPopquizFragment.java index d1f93267a..8321f0f89 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogPopquizFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogPopquizFragment.java @@ -9,28 +9,16 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; -import android.widget.LinearLayout; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; - -import com.airbnb.lottie.LottieAnimationView; - import org.openobservatory.ooniprobe.R; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; +import org.openobservatory.ooniprobe.databinding.FragmentOnboardingDialogPopquizBinding; public class OnboardingDialogPopquizFragment extends DialogFragment { private static final String TITLE_RES_ID = "titleResId"; private static final String QUESTION_RES_ID = "questionResId"; - @BindView(R.id.title) @Nullable TextView title; - @BindView(R.id.question) TextView question; - @BindView(R.id.dialog) LinearLayout dialog; - @BindView(R.id.animation) LottieAnimationView animation; + private FragmentOnboardingDialogPopquizBinding binding; public static OnboardingDialogPopquizFragment newInstance(int titleResId, int questionResId) { Bundle args = new Bundle(); @@ -53,42 +41,45 @@ public void onStart() { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { assert getArguments() != null; - View v = inflater.inflate(R.layout.fragment_onboarding_dialog_popquiz, container, false); - ButterKnife.bind(this, v); - if (title != null) - title.setText(getArguments().getInt(TITLE_RES_ID)); - question.setText(getArguments().getInt(QUESTION_RES_ID)); - return v; + binding = FragmentOnboardingDialogPopquizBinding.inflate(inflater, container, false); + if (binding.title != null) + binding.title.setText(getArguments().getInt(TITLE_RES_ID)); + binding.question.setText(getArguments().getInt(QUESTION_RES_ID)); + + binding.positive.setOnClickListener(v -> positiveClick()); + binding.negative.setOnClickListener(v -> negativeClick()); + + return binding.getRoot(); } - @OnClick(R.id.positive) void positiveClick() { - animation.setBackgroundResource(R.drawable.dialog_green); - animation.setAnimation("anim/checkMark.json"); - animation.setVisibility(View.VISIBLE); - dialog.setVisibility(View.INVISIBLE); - animation.addAnimatorListener(new AnimatorListenerAdapter() { + void positiveClick() { + binding.animation.setBackgroundResource(R.drawable.dialog_green); + binding.animation.setAnimation("anim/checkMark.json"); + binding.animation.setVisibility(View.VISIBLE); + binding.dialog.setVisibility(View.INVISIBLE); + binding.animation.addAnimatorListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { dismiss(); ((OnboardingPopquizInterface) getParentFragment()).onPopquizResult(getArguments().getInt(QUESTION_RES_ID), true); } }); - animation.playAnimation(); + binding.animation.playAnimation(); } - @OnClick(R.id.negative) void negativeClick() { - animation.setBackgroundResource(R.drawable.dialog_red); - animation.setAnimation("anim/crossMark.json"); - animation.setVisibility(View.VISIBLE); - dialog.setVisibility(View.INVISIBLE); - animation.addAnimatorListener(new AnimatorListenerAdapter() { + void negativeClick() { + binding.animation.setBackgroundResource(R.drawable.dialog_red); + binding.animation.setAnimation("anim/crossMark.json"); + binding.animation.setVisibility(View.VISIBLE); + binding.dialog.setVisibility(View.INVISIBLE); + binding.animation.addAnimatorListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { dismiss(); ((OnboardingPopquizInterface) getParentFragment()).onPopquizResult(getArguments().getInt(QUESTION_RES_ID), false); } }); - animation.playAnimation(); + binding.animation.playAnimation(); } public interface OnboardingPopquizInterface { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogWarningFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogWarningFragment.java index 5cc405474..f8e6102eb 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogWarningFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/onboarding/OnboardingDialogWarningFragment.java @@ -7,24 +7,13 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; -import android.widget.LinearLayout; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; - -import org.openobservatory.ooniprobe.R; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; +import org.openobservatory.ooniprobe.databinding.FragmentOnboardingDialogWarningBinding; public class OnboardingDialogWarningFragment extends DialogFragment { private static final String QUESTION_RES_ID = "questionResId"; - @BindView(R.id.title) @Nullable TextView title; - @BindView(R.id.question) TextView question; - @BindView(R.id.dialog) LinearLayout dialog; public static OnboardingDialogWarningFragment newInstance(int questionResId) { Bundle args = new Bundle(); @@ -46,17 +35,20 @@ public void onStart() { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { assert getArguments() != null; - View v = inflater.inflate(R.layout.fragment_onboarding_dialog_warning, container, false); - ButterKnife.bind(this, v); - question.setText(getArguments().getInt(QUESTION_RES_ID)); - return v; + FragmentOnboardingDialogWarningBinding binding = FragmentOnboardingDialogWarningBinding.inflate(inflater, container, false); + binding.question.setText(getArguments().getInt(QUESTION_RES_ID)); + + binding.positive.setOnClickListener(v -> positiveClick()); + binding.negative.setOnClickListener(v -> negativeClick()); + + return binding.getRoot(); } - @OnClick(R.id.positive) void positiveClick() { + void positiveClick() { dismiss(); } - @OnClick(R.id.negative) void negativeClick() { + void negativeClick() { dismiss(); ((OnboardingWarningInterface) getParentFragment()).onWarningResult(getArguments().getInt(QUESTION_RES_ID)); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderDetailFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderDetailFragment.java index 45331eb23..4f9130576 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderDetailFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderDetailFragment.java @@ -5,23 +5,17 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.view.ContextThemeWrapper; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentResultHeadDetailBinding; import org.openobservatory.ooniprobe.model.database.Network; import java.util.Date; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; - public class ResultHeaderDetailFragment extends Fragment { private static final String NETWORK = "network"; private static final String COUNTRY_CODE = "country_code"; @@ -31,19 +25,6 @@ public class ResultHeaderDetailFragment extends Fragment { private static final String START_TIME = "start_time"; private static final String IS_TOTAL_RUNTIME = "isTotalRuntime"; private static final String LIGHT_THEME = "lightTheme"; - @BindView(R.id.dataUsage) LinearLayout dataUsage; - @BindView(R.id.startTimeBox) LinearLayout startTimeBox; - @BindView(R.id.runtimeBox) LinearLayout runtimeBox; - @BindView(R.id.countryBox) LinearLayout countryBox; - @BindView(R.id.networkBox) LinearLayout networkBox; - @BindView(R.id.startTime) TextView startTime; - @BindView(R.id.upload) TextView upload; - @BindView(R.id.download) TextView download; - @BindView(R.id.runtime) TextView runtime; - @BindView(R.id.runtimeLabel) TextView runtimeLabel; - @BindView(R.id.country) TextView country; - @BindView(R.id.networkName) TextView networkName; - @BindView(R.id.networkDetail) TextView networkDetail; public static ResultHeaderDetailFragment newInstance(boolean lightTheme, String data_usage_up, String data_usage_down, Date start_time, Double runtime, Boolean isTotalRuntime, String country_code, Network network) { Bundle args = new Bundle(); @@ -67,35 +48,42 @@ public static ResultHeaderDetailFragment newInstance(boolean lightTheme, String return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; int themeResId = getArguments().getBoolean(LIGHT_THEME) ? R.style.Theme_MaterialComponents_Light_NoActionBar_App : R.style.Theme_MaterialComponents_NoActionBar_App; - View v = inflater.cloneInContext(new ContextThemeWrapper(getActivity(), themeResId)).inflate(R.layout.fragment_result_head_detail, container, false); - ButterKnife.bind(this, v); + FragmentResultHeadDetailBinding binding = FragmentResultHeadDetailBinding.inflate(inflater.cloneInContext(new ContextThemeWrapper(getActivity(), themeResId)), container, false); if (getArguments().containsKey(DATA_USAGE_DOWN) && getArguments().containsKey(DATA_USAGE_UP)) { - download.setText(getArguments().getString(DATA_USAGE_DOWN)); - upload.setText(getArguments().getString(DATA_USAGE_UP)); + binding.download.setText(getArguments().getString(DATA_USAGE_DOWN)); + binding.upload.setText(getArguments().getString(DATA_USAGE_UP)); } else - dataUsage.setVisibility(View.GONE); + binding.dataUsage.setVisibility(View.GONE); if (getArguments().containsKey(START_TIME)) - startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), (Date) getArguments().getSerializable(START_TIME))); + binding.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), (Date) getArguments().getSerializable(START_TIME))); else - startTimeBox.setVisibility(View.GONE); + binding.startTimeBox.setVisibility(View.GONE); if (getArguments().containsKey(RUNTIME)) { - runtime.setText(getString(R.string.f, getArguments().getDouble(RUNTIME))); - runtimeLabel.setText(getArguments().getBoolean(IS_TOTAL_RUNTIME) ? R.string.TestResults_Summary_Hero_Runtime : R.string.TestResults_Details_Hero_Runtime); + binding.runtime.setText(getString(R.string.f, getArguments().getDouble(RUNTIME))); + binding.runtimeLabel.setText(getArguments().getBoolean(IS_TOTAL_RUNTIME) ? R.string.TestResults_Summary_Hero_Runtime : R.string.TestResults_Details_Hero_Runtime); } else - runtimeBox.setVisibility(View.GONE); + binding.runtimeBox.setVisibility(View.GONE); if (getArguments().containsKey(COUNTRY_CODE)) - country.setText(getArguments().getString(COUNTRY_CODE)); + binding.country.setText(getArguments().getString(COUNTRY_CODE)); else - countryBox.setVisibility(View.GONE); + binding.countryBox.setVisibility(View.GONE); if (getArguments().containsKey(NETWORK)) { Network n = (Network) getArguments().getSerializable(NETWORK); - networkName.setText(Network.getName(networkName.getContext(), n)); - networkDetail.setText(networkDetail.getContext().getString(R.string.twoParamWithBrackets, Network.getAsn(networkDetail.getContext(), n), Network.getLocalizedNetworkType(networkDetail.getContext(), n))); + binding.networkName.setText(Network.getName(binding.networkName.getContext(), n)); + binding.networkDetail.setText( + binding.networkDetail.getContext().getString( + R.string.twoParamWithBrackets, + Network.getAsn(binding.networkDetail.getContext(), n), + Network.getLocalizedNetworkType(binding.networkDetail.getContext(), n) + ) + ); } else - networkBox.setVisibility(View.GONE); - return v; + binding.networkBox.setVisibility(View.GONE); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderMiddleboxFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderMiddleboxFragment.java index 3e4137ccc..c70441cb4 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderMiddleboxFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderMiddleboxFragment.java @@ -5,20 +5,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentResultHeadMiddleboxBinding; -import butterknife.BindView; -import butterknife.ButterKnife; - -@Deprecated public class ResultHeaderMiddleboxFragment extends Fragment { +@Deprecated +public class ResultHeaderMiddleboxFragment extends Fragment { private static final String ANOMALY = "anomaly"; - @BindView(R.id.text) TextView text; public static ResultHeaderMiddleboxFragment newInstance(boolean anomaly) { Bundle args = new Bundle(); @@ -28,11 +23,20 @@ public static ResultHeaderMiddleboxFragment newInstance(boolean anomaly) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; - View v = inflater.inflate(R.layout.fragment_result_head_middlebox, container, false); - ButterKnife.bind(this, v); - text.setText(Html.fromHtml(v.getContext().getString(R.string.normalBold, getString(R.string.Test_Middleboxes_Fullname), getString(getArguments().getBoolean(ANOMALY) ? R.string.TestResults_Summary_Middleboxes_Hero_Found : R.string.TestResults_Summary_Middleboxes_Hero_NotFound)))); - return v; + FragmentResultHeadMiddleboxBinding binding = FragmentResultHeadMiddleboxBinding.inflate(inflater, container, false); + binding.text.setText( + Html.fromHtml( + binding.getRoot().getContext().getString( + R.string.normalBold, + getString(R.string.Test_Middleboxes_Fullname), + getString(getArguments().getBoolean(ANOMALY) ? R.string.TestResults_Summary_Middleboxes_Hero_Found : R.string.TestResults_Summary_Middleboxes_Hero_NotFound) + ) + ) + ); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderPerformanceFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderPerformanceFragment.java index d69da9b36..8ae44721f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderPerformanceFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderPerformanceFragment.java @@ -4,37 +4,20 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentResultHeadPerformanceBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.test.test.Dash; import org.openobservatory.ooniprobe.test.test.Ndt; -import butterknife.BindView; -import butterknife.ButterKnife; - public class ResultHeaderPerformanceFragment extends Fragment { private static final String RESULT = "result"; public static final float ALPHA_DIS = 0.3f; public static final int ALPHA_ENA = 1; - @BindView(R.id.video) TextView video; - @BindView(R.id.upload) TextView upload; - @BindView(R.id.download) TextView download; - @BindView(R.id.ping) TextView ping; - @BindView(R.id.videoLabel) TextView videoLabel; - @BindView(R.id.downloadLabel) TextView downloadLabel; - @BindView(R.id.uploadLabel) TextView uploadLabel; - @BindView(R.id.pingLabel) TextView pingLabel; - @BindView(R.id.videoUnit) TextView videoUnit; - @BindView(R.id.downloadUnit) TextView downloadUnit; - @BindView(R.id.uploadUnit) TextView uploadUnit; - @BindView(R.id.pingUnit) TextView pingUnit; public static ResultHeaderPerformanceFragment newInstance(Result result) { Bundle args = new Bundle(); @@ -44,32 +27,33 @@ public static ResultHeaderPerformanceFragment newInstance(Result result) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; - View v = inflater.inflate(R.layout.fragment_result_head_performance, container, false); - ButterKnife.bind(this, v); + FragmentResultHeadPerformanceBinding binding = FragmentResultHeadPerformanceBinding.inflate(inflater, container, false); Result result = (Result) getArguments().getSerializable(RESULT); assert result != null; Measurement dashM = result.getMeasurement(Dash.NAME); Measurement ndtM = result.getMeasurement(Ndt.NAME); - video.setText(dashM == null ? R.string.TestResults_NotAvailable : dashM.getTestKeys().getVideoQuality(false)); - upload.setText(ndtM == null ? getString(R.string.TestResults_NotAvailable) : ndtM.getTestKeys().getUpload(getActivity())); - uploadUnit.setText(ndtM == null ? R.string.TestResults_NotAvailable : ndtM.getTestKeys().getUploadUnit()); - download.setText(ndtM == null ? getString(R.string.TestResults_NotAvailable) : ndtM.getTestKeys().getDownload(getActivity())); - downloadUnit.setText(ndtM == null ? R.string.TestResults_NotAvailable : ndtM.getTestKeys().getDownloadUnit()); - ping.setText(ndtM == null ? getString(R.string.TestResults_NotAvailable) : ndtM.getTestKeys().getPing(getActivity())); - videoLabel.setAlpha(dashM == null ? ALPHA_DIS : ALPHA_ENA); - downloadLabel.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - uploadLabel.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - pingLabel.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - video.setAlpha(dashM == null ? ALPHA_DIS : ALPHA_ENA); - download.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - upload.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - ping.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - videoUnit.setAlpha(dashM == null ? ALPHA_DIS : ALPHA_ENA); - downloadUnit.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - uploadUnit.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - pingUnit.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); - return v; + binding.video.setText(dashM == null ? R.string.TestResults_NotAvailable : dashM.getTestKeys().getVideoQuality(false)); + binding.upload.setText(ndtM == null ? getString(R.string.TestResults_NotAvailable) : ndtM.getTestKeys().getUpload(getActivity())); + binding.uploadUnit.setText(ndtM == null ? R.string.TestResults_NotAvailable : ndtM.getTestKeys().getUploadUnit()); + binding.download.setText(ndtM == null ? getString(R.string.TestResults_NotAvailable) : ndtM.getTestKeys().getDownload(getActivity())); + binding.downloadUnit.setText(ndtM == null ? R.string.TestResults_NotAvailable : ndtM.getTestKeys().getDownloadUnit()); + binding.ping.setText(ndtM == null ? getString(R.string.TestResults_NotAvailable) : ndtM.getTestKeys().getPing(getActivity())); + binding.videoLabel.setAlpha(dashM == null ? ALPHA_DIS : ALPHA_ENA); + binding.downloadLabel.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.uploadLabel.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.pingLabel.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.video.setAlpha(dashM == null ? ALPHA_DIS : ALPHA_ENA); + binding.download.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.upload.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.ping.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.videoUnit.setAlpha(dashM == null ? ALPHA_DIS : ALPHA_ENA); + binding.downloadUnit.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.uploadUnit.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + binding.pingUnit.setAlpha(ndtM == null ? ALPHA_DIS : ALPHA_ENA); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderTBAFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderTBAFragment.java index b7a01a0dd..137325d2f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderTBAFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/resultHeader/ResultHeaderTBAFragment.java @@ -4,26 +4,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.FragmentResultHeadTbaBinding; import org.openobservatory.ooniprobe.model.database.Result; -import butterknife.BindView; -import butterknife.ButterKnife; - public class ResultHeaderTBAFragment extends Fragment { private static final String RESULT = "result"; - @BindView(R.id.tested) TextView tested; - @BindView(R.id.blocked) TextView blocked; - @BindView(R.id.available) TextView available; - @BindView(R.id.testedTag) TextView testedTag; - @BindView(R.id.blockedTag) TextView blockedTag; - @BindView(R.id.availableTag) TextView availableTag; public static ResultHeaderTBAFragment newInstance(Result result) { Bundle args = new Bundle(); @@ -33,21 +22,22 @@ public static ResultHeaderTBAFragment newInstance(Result result) { return fragment; } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { assert getArguments() != null; - View v = inflater.inflate(R.layout.fragment_result_head_tba, container, false); - ButterKnife.bind(this, v); + FragmentResultHeadTbaBinding binding = FragmentResultHeadTbaBinding.inflate(inflater, container, false); Result result = (Result) getArguments().getSerializable(RESULT); assert result != null; long testedCount = result.countTotalMeasurements(); long blockedCount = result.countAnomalousMeasurements(); long availableCount = result.countOkMeasurements(); - tested.setText(getString(R.string.d, testedCount)); - blocked.setText(getString(R.string.d, blockedCount)); - available.setText(getString(R.string.d, availableCount)); - testedTag.setText(getResources().getQuantityText(R.plurals.TestResults_Summary_Websites_Hero_Tested, (int) testedCount)); - blockedTag.setText(getResources().getQuantityText(R.plurals.TestResults_Summary_Websites_Hero_Blocked, (int) blockedCount)); - availableTag.setText(getResources().getQuantityText(R.plurals.TestResults_Summary_Websites_Hero_Reachable, (int) availableCount)); - return v; + binding.tested.setText(getString(R.string.d, testedCount)); + binding.blocked.setText(getString(R.string.d, blockedCount)); + binding.available.setText(getString(R.string.d, availableCount)); + binding.testedTag.setText(getResources().getQuantityText(R.plurals.TestResults_Summary_Websites_Hero_Tested, (int) testedCount)); + binding.blockedTag.setText(getResources().getQuantityText(R.plurals.TestResults_Summary_Websites_Hero_Blocked, (int) blockedCount)); + binding.availableTag.setText(getResources().getQuantityText(R.plurals.TestResults_Summary_Websites_Hero_Reachable, (int) availableCount)); + return binding.getRoot(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/CircumventionItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/CircumventionItem.java index f4e8fbc6e..2d54bc237 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/CircumventionItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/CircumventionItem.java @@ -4,23 +4,18 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; - +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemCircumventionBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.model.database.Result; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class CircumventionItem extends HeterogeneousRecyclerItem { private final View.OnClickListener onClickListener; private final View.OnLongClickListener onLongClickListener; @@ -31,39 +26,35 @@ public CircumventionItem(Result extra, View.OnClickListener onClickListener, Vie this.onLongClickListener = onLongClickListener; } - @Override public CircumventionItem.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new CircumventionItem.ViewHolder(layoutInflater.inflate(R.layout.item_circumvention, viewGroup, false)); + @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { + return new ViewHolder(ItemCircumventionBinding.inflate(layoutInflater, viewGroup, false)); } - @Override public void onBindViewHolder(CircumventionItem.ViewHolder viewHolder) { + @Override public void onBindViewHolder(ViewHolder viewHolder) { viewHolder.itemView.setTag(extra); viewHolder.itemView.setOnClickListener(onClickListener); viewHolder.itemView.setOnLongClickListener(onLongClickListener); viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(viewHolder.itemView.getContext(), extra.is_viewed ? android.R.color.transparent : R.color.color_yellow0)); - viewHolder.asnName.setText(Network.toString(viewHolder.asnName.getContext(), extra.network)); - viewHolder.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); + viewHolder.binding.asnName.setText(Network.toString(viewHolder.binding.asnName.getContext(), extra.network)); + viewHolder.binding.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); Long blocked = extra.countAnomalousMeasurements(); Long available = extra.countOkMeasurements(); - viewHolder.failedMeasurements.setText(viewHolder.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Circumvention_Blocked, blocked.intValue(), blocked.toString())); - viewHolder.okMeasurements.setText(viewHolder.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Circumvention_Available, available.intValue(), available.toString())); - viewHolder.failedMeasurements.setTextColor(ContextCompat.getColor(viewHolder.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); - DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.failedMeasurements.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); + viewHolder.binding.failedMeasurements.setText(viewHolder.binding.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Circumvention_Blocked, blocked.intValue(), blocked.toString())); + viewHolder.binding.okMeasurements.setText(viewHolder.binding.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Circumvention_Available, available.intValue(), available.toString())); + viewHolder.binding.failedMeasurements.setTextColor(ContextCompat.getColor(viewHolder.binding.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); + DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.binding.failedMeasurements.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.binding.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); boolean allUploaded = true; for (Measurement m : extra.getMeasurements()) allUploaded = allUploaded && (m.isUploaded() || m.is_failed); - viewHolder.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); + viewHolder.binding.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); } - class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.asnName) - TextView asnName; - @BindView(R.id.startTime) TextView startTime; - @BindView(R.id.failedMeasurements) TextView failedMeasurements; - @BindView(R.id.okMeasurements) TextView okMeasurements; + public static class ViewHolder extends RecyclerView.ViewHolder { + ItemCircumventionBinding binding; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolder(ItemCircumventionBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/DateItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/DateItem.java index 139bfe342..60a6003c5 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/DateItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/DateItem.java @@ -2,20 +2,16 @@ import android.text.format.DateFormat; import android.view.LayoutInflater; -import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; -import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemDateBinding; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class DateItem extends HeterogeneousRecyclerItem { @@ -27,19 +23,19 @@ public DateItem(Date extra) { } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_date, viewGroup, false)); + return new ViewHolder(ItemDateBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { - viewHolder.textView.setText(SDF.format(extra)); + viewHolder.binding.textView.setText(SDF.format(extra)); } class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.textView) TextView textView; + ItemDateBinding binding; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolder(ItemDateBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/ExperimentalItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/ExperimentalItem.java index f38c4b460..e950e0087 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/ExperimentalItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/ExperimentalItem.java @@ -4,11 +4,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; - +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.databinding.ItemExperimentalBinding; import org.openobservatory.ooniprobe.model.database.Measurement; @@ -17,10 +15,6 @@ import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class ExperimentalItem extends HeterogeneousRecyclerItem { private final View.OnClickListener onClickListener; private final View.OnLongClickListener onLongClickListener; @@ -49,7 +43,7 @@ public ExperimentalItem(Result extra, View.OnClickListener onClickListener, View viewHolder.binding.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); } - class ViewHolder extends RecyclerView.ViewHolder { + public static class ViewHolder extends RecyclerView.ViewHolder { ItemExperimentalBinding binding; ViewHolder(ItemExperimentalBinding binding) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/FailedItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/FailedItem.java index f86a9559a..43171a5f4 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/FailedItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/FailedItem.java @@ -4,19 +4,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemFailedBinding; import org.openobservatory.ooniprobe.model.database.Result; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class FailedItem extends HeterogeneousRecyclerItem { @@ -30,7 +27,7 @@ public FailedItem(Result extra, View.OnClickListener onClickListener, View.OnLon } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_failed, viewGroup, false)); + return new ViewHolder(ItemFailedBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { @@ -38,25 +35,22 @@ public FailedItem(Result extra, View.OnClickListener onClickListener, View.OnLon viewHolder.itemView.setOnClickListener(onClickListener); viewHolder.itemView.setOnLongClickListener(onLongClickListener); viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(viewHolder.itemView.getContext(), R.color.color_gray2)); - viewHolder.testName.setTextColor(ContextCompat.getColor(viewHolder.itemView.getContext(), R.color.color_gray6)); - viewHolder.icon.setImageResource(extra.getTestSuite().getIcon()); - viewHolder.testName.setText(extra.getTestSuite().getTitle()); + viewHolder.binding.testName.setTextColor(ContextCompat.getColor(viewHolder.itemView.getContext(), R.color.color_gray6)); + viewHolder.binding.icon.setImageResource(extra.getTestSuite().getIcon()); + viewHolder.binding.testName.setText(extra.getTestSuite().getTitle()); String failure_msg = viewHolder.itemView.getContext().getString(R.string.TestResults_Overview_Error); if (extra.failure_msg != null) failure_msg += " - " + extra.failure_msg; - viewHolder.subtitle.setText(failure_msg); - viewHolder.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); + viewHolder.binding.subtitle.setText(failure_msg); + viewHolder.binding.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); } class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.testName) TextView testName; - @BindView(R.id.subtitle) TextView subtitle; - @BindView(R.id.startTime) TextView startTime; - @BindView(R.id.icon) ImageView icon; - - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ItemFailedBinding binding; + + ViewHolder(ItemFailedBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/InstantMessagingItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/InstantMessagingItem.java index 86fab7fa5..799a7fc3d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/InstantMessagingItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/InstantMessagingItem.java @@ -4,23 +4,18 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; - +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemInstantmessagingBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.model.database.Result; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class InstantMessagingItem extends HeterogeneousRecyclerItem { private final View.OnClickListener onClickListener; private final View.OnLongClickListener onLongClickListener; @@ -32,7 +27,7 @@ public InstantMessagingItem(Result extra, View.OnClickListener onClickListener, } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_instantmessaging, viewGroup, false)); + return new ViewHolder(ItemInstantmessagingBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { @@ -40,29 +35,26 @@ public InstantMessagingItem(Result extra, View.OnClickListener onClickListener, viewHolder.itemView.setOnClickListener(onClickListener); viewHolder.itemView.setOnLongClickListener(onLongClickListener); viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(viewHolder.itemView.getContext(), extra.is_viewed ? android.R.color.transparent : R.color.color_yellow0)); - viewHolder.asnName.setText(Network.toString(viewHolder.asnName.getContext(), extra.network)); - viewHolder.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); + viewHolder.binding.asnName.setText(Network.toString(viewHolder.binding.asnName.getContext(), extra.network)); + viewHolder.binding.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); Long blocked = extra.countAnomalousMeasurements(); Long available = extra.countOkMeasurements(); - viewHolder.failedMeasurements.setText(viewHolder.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_InstantMessaging_Blocked, blocked.intValue(), blocked.toString())); - viewHolder.okMeasurements.setText(viewHolder.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_InstantMessaging_Available, available.intValue(), available.toString())); - viewHolder.failedMeasurements.setTextColor(ContextCompat.getColor(viewHolder.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); - DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.failedMeasurements.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); + viewHolder.binding.failedMeasurements.setText(viewHolder.binding.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_InstantMessaging_Blocked, blocked.intValue(), blocked.toString())); + viewHolder.binding.okMeasurements.setText(viewHolder.binding.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_InstantMessaging_Available, available.intValue(), available.toString())); + viewHolder.binding.failedMeasurements.setTextColor(ContextCompat.getColor(viewHolder.binding.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); + DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.binding.failedMeasurements.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.binding.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); boolean allUploaded = true; for (Measurement m : extra.getMeasurements()) allUploaded = allUploaded && (m.isUploaded() || m.is_failed); - viewHolder.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); + viewHolder.binding.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); } - class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.asnName) TextView asnName; - @BindView(R.id.startTime) TextView startTime; - @BindView(R.id.failedMeasurements) TextView failedMeasurements; - @BindView(R.id.okMeasurements) TextView okMeasurements; + public static class ViewHolder extends RecyclerView.ViewHolder { + ItemInstantmessagingBinding binding; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolder(ItemInstantmessagingBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementItem.java index 570444b1a..fedfa4c6a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementItem.java @@ -11,12 +11,11 @@ import androidx.recyclerview.widget.RecyclerView; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemMeasurementBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.test.test.AbstractTest; import org.openobservatory.ooniprobe.test.test.WebConnectivity; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class MeasurementItem extends HeterogeneousRecyclerItem { @@ -28,7 +27,7 @@ public MeasurementItem(Measurement extra, View.OnClickListener onClickListener) } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_measurement, viewGroup, false)); + return new ViewHolder(ItemMeasurementBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { @@ -65,12 +64,12 @@ else if (extra.isUploaded()) } class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.text) TextView text; + TextView text; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - text.setOnClickListener(onClickListener); + ViewHolder(ItemMeasurementBinding binding) { + super(binding.getRoot()); + this.text = binding.text; + this.text.setOnClickListener(onClickListener); } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementPerfItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementPerfItem.java index 5cffa6903..674f0a837 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementPerfItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/MeasurementPerfItem.java @@ -4,19 +4,17 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemMeasurementPerfBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.test.test.Dash; import org.openobservatory.ooniprobe.test.test.HttpHeaderFieldManipulation; import org.openobservatory.ooniprobe.test.test.HttpInvalidRequestLine; import org.openobservatory.ooniprobe.test.test.Ndt; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class MeasurementPerfItem extends HeterogeneousRecyclerItem { @@ -28,46 +26,43 @@ public MeasurementPerfItem(Measurement extra, View.OnClickListener onClickListen } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_measurement_perf, viewGroup, false)); + return new ViewHolder(ItemMeasurementPerfBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { viewHolder.itemView.setTag(extra); - Context c = viewHolder.text.getContext(); + Context c = viewHolder.binding.text.getContext(); if (extra.getTest().getLabelResId() == (R.string.Test_Experimental_Fullname)) - viewHolder.text.setText(extra.getTest().getName()); + viewHolder.binding.text.setText(extra.getTest().getName()); else - viewHolder.text.setText(extra.getTest().getLabelResId()); - viewHolder.text.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, extra.is_failed || extra.isUploaded() ? 0 : R.drawable.cloudoff, 0); + viewHolder.binding.text.setText(extra.getTest().getLabelResId()); + viewHolder.binding.text.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, extra.is_failed || extra.isUploaded() ? 0 : R.drawable.cloudoff, 0); if (extra.test_name.equals(Dash.NAME)) { - viewHolder.data1.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.video_quality, 0, 0, 0); - viewHolder.data1.setText(extra.getTestKeys().getVideoQuality(true)); - viewHolder.data2.setVisibility(View.GONE); + viewHolder.binding.data1.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.video_quality, 0, 0, 0); + viewHolder.binding.data1.setText(extra.getTestKeys().getVideoQuality(true)); + viewHolder.binding.data2.setVisibility(View.GONE); } else if (extra.test_name.equals(Ndt.NAME)) { - viewHolder.data1.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.download_black, 0, 0, 0); - viewHolder.data1.setText(c.getString(R.string.twoParam, extra.getTestKeys().getDownload(c), c.getString(extra.getTestKeys().getDownloadUnit()))); - viewHolder.data2.setVisibility(View.VISIBLE); - viewHolder.data2.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.upload_black, 0, 0, 0); - viewHolder.data2.setText(c.getString(R.string.twoParam, extra.getTestKeys().getUpload(c), c.getString(extra.getTestKeys().getUploadUnit()))); + viewHolder.binding.data1.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.download_black, 0, 0, 0); + viewHolder.binding.data1.setText(c.getString(R.string.twoParam, extra.getTestKeys().getDownload(c), c.getString(extra.getTestKeys().getDownloadUnit()))); + viewHolder.binding.data2.setVisibility(View.VISIBLE); + viewHolder.binding.data2.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.upload_black, 0, 0, 0); + viewHolder.binding.data2.setText(c.getString(R.string.twoParam, extra.getTestKeys().getUpload(c), c.getString(extra.getTestKeys().getUploadUnit()))); } else if (extra.test_name.equals(HttpHeaderFieldManipulation.NAME) || extra.test_name.equals(HttpInvalidRequestLine.NAME)) { - viewHolder.data1.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.test_middle_boxes_small, 0, 0, 0); - viewHolder.data1.setText(extra.is_anomaly ? + viewHolder.binding.data1.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.test_middle_boxes_small, 0, 0, 0); + viewHolder.binding.data1.setText(extra.is_anomaly ? c.getString(R.string.TestResults_Overview_MiddleBoxes_Found) : c.getString(R.string.TestResults_Overview_MiddleBoxes_NotFound)); - viewHolder.data2.setVisibility(View.GONE); + viewHolder.binding.data2.setVisibility(View.GONE); } } class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.text) TextView text; - @BindView(R.id.data1) TextView data1; - @BindView(R.id.data2) TextView data2; - - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - itemView.setOnClickListener(onClickListener); + ItemMeasurementPerfBinding binding; + ViewHolder(ItemMeasurementPerfBinding binding) { + super(binding.getRoot()); + this.binding = binding; + binding.getRoot().setOnClickListener(onClickListener); } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/MiddleboxesItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/MiddleboxesItem.java index f776347cb..df9aeefc8 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/MiddleboxesItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/MiddleboxesItem.java @@ -4,23 +4,18 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; - +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemMiddleboxesBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.model.database.Result; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - /** * @deprecated * It is not possible to run a MiddleBoxesSuite anymore @@ -38,7 +33,7 @@ public MiddleboxesItem(Result extra, View.OnClickListener onClickListener, View. } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_middleboxes, viewGroup, false)); + return new ViewHolder(ItemMiddleboxesBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { @@ -46,35 +41,33 @@ public MiddleboxesItem(Result extra, View.OnClickListener onClickListener, View. viewHolder.itemView.setOnClickListener(onClickListener); viewHolder.itemView.setOnLongClickListener(onLongClickListener); viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(viewHolder.itemView.getContext(), extra.is_viewed ? android.R.color.transparent : R.color.color_yellow0)); - viewHolder.asnName.setText(Network.toString(viewHolder.asnName.getContext(), extra.network)); - viewHolder.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); + viewHolder.binding.asnName.setText(Network.toString(viewHolder.binding.asnName.getContext(), extra.network)); + viewHolder.binding.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); if (extra.countAnomalousMeasurements() > 0) { - viewHolder.status.setText(R.string.TestResults_Overview_MiddleBoxes_Found); - viewHolder.status.setTextColor(ContextCompat.getColor(viewHolder.status.getContext(), R.color.color_yellow9)); - DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.status.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.status.getContext(), R.color.color_yellow9)); + viewHolder.binding.status.setText(R.string.TestResults_Overview_MiddleBoxes_Found); + viewHolder.binding.status.setTextColor(ContextCompat.getColor(viewHolder.binding.status.getContext(), R.color.color_yellow9)); + DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.binding.status.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.binding.status.getContext(), R.color.color_yellow9)); } else if (extra.countCompletedMeasurements() == 0) { - viewHolder.status.setText(R.string.TestResults_Overview_MiddleBoxes_Failed); - viewHolder.status.setTextColor(ContextCompat.getColor(viewHolder.status.getContext(), R.color.color_gray9)); - DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.status.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.status.getContext(), R.color.color_gray9)); + viewHolder.binding.status.setText(R.string.TestResults_Overview_MiddleBoxes_Failed); + viewHolder.binding.status.setTextColor(ContextCompat.getColor(viewHolder.binding.status.getContext(), R.color.color_gray9)); + DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.binding.status.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.binding.status.getContext(), R.color.color_gray9)); } else { - viewHolder.status.setText(R.string.TestResults_Overview_MiddleBoxes_NotFound); - viewHolder.status.setTextColor(ContextCompat.getColor(viewHolder.status.getContext(), R.color.color_gray9)); - DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.status.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.status.getContext(), R.color.color_gray9)); + viewHolder.binding.status.setText(R.string.TestResults_Overview_MiddleBoxes_NotFound); + viewHolder.binding.status.setTextColor(ContextCompat.getColor(viewHolder.binding.status.getContext(), R.color.color_gray9)); + DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.binding.status.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.binding.status.getContext(), R.color.color_gray9)); } boolean allUploaded = true; for (Measurement m : extra.getMeasurements()) allUploaded = allUploaded && (m.isUploaded() || m.is_failed); - viewHolder.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); + viewHolder.binding.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); } - class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.asnName) TextView asnName; - @BindView(R.id.startTime) TextView startTime; - @BindView(R.id.status) TextView status; + public static class ViewHolder extends RecyclerView.ViewHolder { + ItemMiddleboxesBinding binding; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolder(ItemMiddleboxesBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/PerformanceItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/PerformanceItem.java index af9d6dff2..ac29d1292 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/PerformanceItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/PerformanceItem.java @@ -5,12 +5,11 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; - +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemPerformanceBinding; import org.openobservatory.ooniprobe.fragment.resultHeader.ResultHeaderPerformanceFragment; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; @@ -20,10 +19,6 @@ import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class PerformanceItem extends HeterogeneousRecyclerItem { private final View.OnClickListener onClickListener; private final View.OnLongClickListener onLongClickListener; @@ -35,7 +30,7 @@ public PerformanceItem(Result extra, View.OnClickListener onClickListener, View. } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_performance, viewGroup, false)); + return new ViewHolder(ItemPerformanceBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { @@ -44,32 +39,28 @@ public PerformanceItem(Result extra, View.OnClickListener onClickListener, View. viewHolder.itemView.setOnClickListener(onClickListener); viewHolder.itemView.setOnLongClickListener(onLongClickListener); viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(c, extra.is_viewed ? android.R.color.transparent : R.color.color_yellow0)); - viewHolder.asnName.setText(Network.toString(viewHolder.asnName.getContext(), extra.network)); - viewHolder.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); + viewHolder.binding.asnName.setText(Network.toString(viewHolder.binding.asnName.getContext(), extra.network)); + viewHolder.binding.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); Measurement dashM = extra.getMeasurement(Dash.NAME); Measurement ndtM = extra.getMeasurement(Ndt.NAME); - viewHolder.quality.setText(dashM == null ? R.string.TestResults_NotAvailable : dashM.getTestKeys().getVideoQuality(false)); - viewHolder.upload.setText(ndtM == null ? c.getString(R.string.TestResults_NotAvailable) : c.getString(R.string.twoParam, ndtM.getTestKeys().getUpload(c), c.getString(ndtM.getTestKeys().getUploadUnit()))); - viewHolder.download.setText(ndtM == null ? c.getString(R.string.TestResults_NotAvailable) : c.getString(R.string.twoParam, ndtM.getTestKeys().getDownload(c), c.getString(ndtM.getTestKeys().getDownloadUnit()))); - viewHolder.quality.setAlpha(dashM == null ? ResultHeaderPerformanceFragment.ALPHA_DIS : ResultHeaderPerformanceFragment.ALPHA_ENA); - viewHolder.upload.setAlpha(ndtM == null ? ResultHeaderPerformanceFragment.ALPHA_DIS : ResultHeaderPerformanceFragment.ALPHA_ENA); - viewHolder.download.setAlpha(ndtM == null ? ResultHeaderPerformanceFragment.ALPHA_DIS : ResultHeaderPerformanceFragment.ALPHA_ENA); + viewHolder.binding.quality.setText(dashM == null ? R.string.TestResults_NotAvailable : dashM.getTestKeys().getVideoQuality(false)); + viewHolder.binding.upload.setText(ndtM == null ? c.getString(R.string.TestResults_NotAvailable) : c.getString(R.string.twoParam, ndtM.getTestKeys().getUpload(c), c.getString(ndtM.getTestKeys().getUploadUnit()))); + viewHolder.binding.download.setText(ndtM == null ? c.getString(R.string.TestResults_NotAvailable) : c.getString(R.string.twoParam, ndtM.getTestKeys().getDownload(c), c.getString(ndtM.getTestKeys().getDownloadUnit()))); + viewHolder.binding.quality.setAlpha(dashM == null ? ResultHeaderPerformanceFragment.ALPHA_DIS : ResultHeaderPerformanceFragment.ALPHA_ENA); + viewHolder.binding.upload.setAlpha(ndtM == null ? ResultHeaderPerformanceFragment.ALPHA_DIS : ResultHeaderPerformanceFragment.ALPHA_ENA); + viewHolder.binding.download.setAlpha(ndtM == null ? ResultHeaderPerformanceFragment.ALPHA_DIS : ResultHeaderPerformanceFragment.ALPHA_ENA); boolean allUploaded = true; for (Measurement m : extra.getMeasurements()) allUploaded = allUploaded && (m.isUploaded() || m.is_failed); - viewHolder.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); + viewHolder.binding.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); } - class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.asnName) TextView asnName; - @BindView(R.id.startTime) TextView startTime; - @BindView(R.id.upload) TextView upload; - @BindView(R.id.download) TextView download; - @BindView(R.id.quality) TextView quality; + public static class ViewHolder extends RecyclerView.ViewHolder { + ItemPerformanceBinding binding; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolder(ItemPerformanceBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } 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..70c971b22 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/SeperatorItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/SeperatorItem.java @@ -1,14 +1,12 @@ package org.openobservatory.ooniprobe.item; import android.view.LayoutInflater; -import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.RecyclerView; -import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemSeperatorBinding; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class SeperatorItem extends HeterogeneousRecyclerItem { @@ -18,15 +16,14 @@ public SeperatorItem() { } @Override public ViewHolderImpl onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolderImpl(layoutInflater.inflate(R.layout.item_seperator, viewGroup, false)); + return new ViewHolderImpl(ItemSeperatorBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolderImpl holder) {} static class ViewHolderImpl extends RecyclerView.ViewHolder { - ViewHolderImpl(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolderImpl(ItemSeperatorBinding binding) { + super(binding.getRoot()); } } } 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 98fb0f70c..9eb8bf60b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/TestsuiteItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/TestsuiteItem.java @@ -1,27 +1,18 @@ package org.openobservatory.ooniprobe.item; -import android.content.Context; import android.content.res.Resources; -import android.graphics.Color; import android.graphics.PorterDuff; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - import androidx.cardview.widget.CardView; -import androidx.constraintlayout.widget.ConstraintLayout; import androidx.recyclerview.widget.RecyclerView; - +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.PreferenceManager; +import org.openobservatory.ooniprobe.databinding.ItemTestsuiteBinding; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class TestsuiteItem extends HeterogeneousRecyclerItem { private final View.OnClickListener onClickListener; private final PreferenceManager preferenceManager; @@ -33,21 +24,21 @@ public TestsuiteItem(AbstractSuite extra, View.OnClickListener onClickListener, } @Override public ViewHolderImpl onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolderImpl(layoutInflater.inflate(R.layout.item_testsuite, viewGroup, false)); + return new ViewHolderImpl(ItemTestsuiteBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolderImpl holder) { - holder.title.setText(extra.getTitle()); - holder.desc.setText(extra.getCardDesc()); - holder.icon.setImageResource(extra.getIconGradient()); + holder.binding.title.setText(extra.getTitle()); + holder.binding.desc.setText(extra.getCardDesc()); + holder.binding.icon.setImageResource(extra.getIconGradient()); holder.itemView.setTag(extra); if(extra.isTestEmpty(preferenceManager)) { ((CardView)holder.itemView).setElevation(0); Resources resources = holder.itemView.getContext().getResources(); ((CardView)holder.itemView).setCardBackgroundColor(resources.getColor(R.color.disabled_test_background)); - holder.title.setTextColor(resources.getColor(R.color.disabled_test_text)); - holder.desc.setTextColor(resources.getColor(R.color.disabled_test_text)); - holder.icon.setColorFilter(resources.getColor(R.color.disabled_test_text), PorterDuff.Mode.SRC_IN); + holder.binding.title.setTextColor(resources.getColor(R.color.disabled_test_text)); + holder.binding.desc.setTextColor(resources.getColor(R.color.disabled_test_text)); + holder.binding.icon.setColorFilter(resources.getColor(R.color.disabled_test_text), PorterDuff.Mode.SRC_IN); holder.setIsRecyclable(false); holder.itemView.setClickable(false); } else { @@ -55,14 +46,12 @@ public TestsuiteItem(AbstractSuite extra, View.OnClickListener onClickListener, } } - class ViewHolderImpl extends RecyclerView.ViewHolder { - @BindView(R.id.title) TextView title; - @BindView(R.id.desc) TextView desc; - @BindView(R.id.icon) ImageView icon; + static class ViewHolderImpl extends RecyclerView.ViewHolder { + ItemTestsuiteBinding binding; - ViewHolderImpl(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolderImpl(ItemTestsuiteBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/TextItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/TextItem.java index 9d0bdb097..f3e6349c4 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/TextItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/TextItem.java @@ -1,16 +1,12 @@ package org.openobservatory.ooniprobe.item; import android.view.LayoutInflater; -import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; -import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemTextBinding; -import butterknife.BindView; -import butterknife.ButterKnife; import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; public class TextItem extends HeterogeneousRecyclerItem { @@ -19,19 +15,19 @@ public TextItem(String extra) { } @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_text, viewGroup, false)); + return new ViewHolder(ItemTextBinding.inflate(layoutInflater, viewGroup, false)); } @Override public void onBindViewHolder(ViewHolder viewHolder) { - viewHolder.textView.setText(extra); + viewHolder.binding.textView.setText(extra); } class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.textView) TextView textView; + ItemTextBinding binding; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolder(ItemTextBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java index 572f00c24..60d9f0589 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java @@ -4,23 +4,18 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; - import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; - +import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ItemWebsitesBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.model.database.Result; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; -import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; - public class WebsiteItem extends HeterogeneousRecyclerItem { private final View.OnClickListener onClickListener; private final View.OnLongClickListener onLongClickListener; @@ -31,38 +26,37 @@ public WebsiteItem(Result extra, View.OnClickListener onClickListener, View.OnLo this.onLongClickListener = onLongClickListener; } - @Override public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return new ViewHolder(layoutInflater.inflate(R.layout.item_websites, viewGroup, false)); + @Override + public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup viewGroup) { + return new ViewHolder(ItemWebsitesBinding.inflate(layoutInflater, viewGroup, false)); } - @Override public void onBindViewHolder(ViewHolder viewHolder) { + @Override + public void onBindViewHolder(ViewHolder viewHolder) { viewHolder.itemView.setTag(extra); viewHolder.itemView.setOnClickListener(onClickListener); viewHolder.itemView.setOnLongClickListener(onLongClickListener); viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(viewHolder.itemView.getContext(), extra.is_viewed ? android.R.color.transparent : R.color.color_yellow0)); - viewHolder.asnName.setText(Network.toString(viewHolder.asnName.getContext(), extra.network)); - viewHolder.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); + viewHolder.binding.asnName.setText(Network.toString(viewHolder.binding.asnName.getContext(), extra.network)); + viewHolder.binding.startTime.setText(DateFormat.format(DateFormat.getBestDateTimePattern(Locale.getDefault(), "yMdHm"), extra.start_time)); Long blocked = extra.countAnomalousMeasurements(); Long tested = extra.countTotalMeasurements(); - viewHolder.failedMeasurements.setText(viewHolder.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Websites_Blocked, blocked.intValue(), blocked.toString())); - viewHolder.testedMeasurements.setText(viewHolder.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Websites_Tested, tested.intValue(), tested.toString())); - viewHolder.failedMeasurements.setTextColor(ContextCompat.getColor(viewHolder.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); - DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.failedMeasurements.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); + viewHolder.binding.failedMeasurements.setText(viewHolder.binding.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Websites_Blocked, blocked.intValue(), blocked.toString())); + viewHolder.binding.testedMeasurements.setText(viewHolder.binding.failedMeasurements.getContext().getResources().getQuantityString(R.plurals.TestResults_Overview_Websites_Tested, tested.intValue(), tested.toString())); + viewHolder.binding.failedMeasurements.setTextColor(ContextCompat.getColor(viewHolder.binding.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); + DrawableCompat.setTint(DrawableCompat.wrap(viewHolder.binding.failedMeasurements.getCompoundDrawablesRelative()[0]).mutate(), ContextCompat.getColor(viewHolder.binding.failedMeasurements.getContext(), blocked == 0 ? R.color.color_gray9 : R.color.color_yellow9)); boolean allUploaded = true; for (Measurement m : extra.getMeasurements()) allUploaded = allUploaded && (m.isUploaded() || m.is_failed); - viewHolder.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); + viewHolder.binding.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); } - class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.asnName) TextView asnName; - @BindView(R.id.startTime) TextView startTime; - @BindView(R.id.failedMeasurements) TextView failedMeasurements; - @BindView(R.id.testedMeasurements) TextView testedMeasurements; + public static class ViewHolder extends RecyclerView.ViewHolder { + ItemWebsitesBinding binding; - ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); + ViewHolder(ItemWebsitesBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 5d3e685cd..f7e642221 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -64,6 +64,7 @@ public class TestAsyncTask extends AsyncTask implements Abst private String proxy; private boolean store_db = true; + private boolean unattended; public static List getSuites() { return Arrays.asList(new WebsitesSuite(), new InstantMessagingSuite(), new CircumventionSuite(), new PerformanceSuite(), new ExperimentalSuite()); @@ -75,9 +76,10 @@ public TestAsyncTask(Application app, ArrayList testSuites) { this.proxy = app.getPreferenceManager().getProxyURL(); } - public TestAsyncTask(Application app, ArrayList testSuites, boolean store_db) { + public TestAsyncTask(Application app, ArrayList testSuites, boolean store_db, boolean unattended) { this(app, testSuites); this.store_db = store_db; + this.unattended = unattended; } private void registerConnChange() { @@ -159,8 +161,15 @@ private void runTest(AbstractTest... tests) { //This uses the wrapper private void downloadURLs() { try { - OONISession session = EngineProvider.get().newSession(EngineProvider.get().getDefaultSessionConfig( - app, BuildConfig.SOFTWARE_NAME, BuildConfig.VERSION_NAME, new LoggerArray(), proxy)); + OONISession session = EngineProvider.get().newSession( + EngineProvider.get().getDefaultSessionConfig( + app, + unattended ? String.join("-", BuildConfig.SOFTWARE_NAME, AbstractTest.UNATTENDED) : BuildConfig.SOFTWARE_NAME, + BuildConfig.VERSION_NAME, + new LoggerArray(), + proxy + ) + ); OONIContext ooniContext = session.newContextWithTimeout(30); OONICheckInConfig config = app.getOONICheckInConfig(); diff --git a/app/src/main/res/layout/fragment_result_list.xml b/app/src/main/res/layout/fragment_result_list.xml index 8ca0d9956..6d016e49c 100644 --- a/app/src/main/res/layout/fragment_result_list.xml +++ b/app/src/main/res/layout/fragment_result_list.xml @@ -141,7 +141,7 @@ android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> - @@ -160,7 +160,7 @@ android:entries="@array/filterTests" android:paddingVertical="8dp" android:textAlignment="center" /> - + - \ No newline at end of file + diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml new file mode 100644 index 000000000..3fa7ffd7c --- /dev/null +++ b/app/src/main/res/values-my/strings.xml @@ -0,0 +1,533 @@ + + + OONI Probe + OONI Probe ဆိုတာ ဘာလဲ။ + သင့်အက်ပ်သည် အင်တာနက် ဆင်ဆာဖြတ်တောက်မှုကို တိုင်းတာရန်။\n\nဝဘ်ဆိုက်များနှင့် ဆိုရှယ်မီဒီယာအက်ပ်များကို ပိတ်ဆို့ နေပါသလား။ သင့်အင်တာနက် ချိတ်ဆက်မှုသည် ပုံမှန်မဟုတ်ဘဲ နှေးနေပါသလား။\n\n၄င်းအကြောင်းအရာတို့ကို သိရှိရန် OONI Probe ကိုဖွင့်ပါ။ + ရပြီ + ကြိုတင်အသိပေးသည်။ + OONI ဒေတာကို ပွင့်လင်းမြင်သာစွာ ထုတ်ဝေထားပြီး သင့်ကွန်ရက် အချက်အလက် များကိုလည်း ပါဝင်မည် ဖြစ်သည်။ + သင့် အင်တာနက် အသုံးပြုမှုကို စောင့်ကြည့်နေသူတိုင်း (အစိုးရ သို့မဟုတ် အင်တာနက် ဝန်ဆောင်မှု ပံ့ပိုးသူ) သည် OONI Probe အား သင် အသုံးပြုနေကြောင်း တွေ့မြင်ရမည်။ + တားမြစ်ထားသော ဝဘ်ဆိုဒ်များကို သင် စမ်းသပ်နိုင်သည် (သို့သော် စမ်းသပ်မည့် ဆိုဒ်များကို သင် ရွေးချယ်နိုင်သည်)။ + နားလည်သည် + ပိုမိုလေ့လာရန် + လျှပ်တပြက် ဉာဏ်စမ်း + မှန်သည် + မှားသည် + နောက်သို့ + ဆက်လုပ်မည် + မေးခွန်း ၁/၂ + တစ်စုံတစ်ယောက်သည် ကျွန်ုပ်၏ အင်တာနက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နေပါက၊ ကျွန်ုပ်သည် OONI Probe ကို အသုံးပြုနေကြောင်း ၎င်းတို့ မြင်တွေ့ရမည် ဖြစ်သည်။ + သတိပေးချက် + OONI Probe သည် ကိုယ်ရေးလုံခြုံမှု ကိရိယာတစ်ခု မဟုတ်ပါ။ သင့် အင်တာနက် လုပ်ဆောင်ချက်များကို စောင့်ကြည့် နေသူတိုင်းသည် သင် အသုံးပြုနေသည့် ဆော့ဖ်ဝဲလ်ကို သိပါလိမ့်မည်။ + မေးခွန်း ၂/၂ + OONI Probe ကို ကျွန်ုပ်အသုံးပြုတိုင်း၊ ကျွန်ုပ် စုဆောင်းထားသော ကွန်ရက်ဒေတာကို အလိုအလျောက် ထုတ်ဝေပါမည်။ + သတိပေးချက် + အင်တာနက် ဆင်ဆာဖြတ်တောက်မှု ပွင့်လင်းမြင်သာရေး တိုးမြင့်စေရန် OONI Probe အသုံးပြုသူများ အားလုံး၏ ကွန်ရက် ဒေတာများအား အလိုအလျောက် ထုတ်ဝေပါမည် (ဆက်တင်တွင် ရွေးချယ်ထားပါက)။ + အလိုအလျောက် စမ်းသပ်ခြင်း + နေ့စဉ် အင်တာနက် ဆင်ဆာဖြတ်တောက်မှုကို တိုင်းတာရန်အတွက် OONI Probe သည် စမ်းသပ်မှုများကို အခါအားလျော်စွာ လုပ်ဆောင်နိုင်စေရန် အလိုအလျောက် စမ်းသပ်မှုကို ဖွင့်ပါ။\n\nစိတ်မပူပါနှင့်၊ ဘက်ထရီ အသုံးပြုမှုကို ကျွန်ုပ်တို့ သတိထားပါမည်။\n\nဆက်တင်များမှ အလိုအလျောက် စမ်းသပ်ခြင်းကို အချိန်မရွေး ပိတ်နိုင်သည်။ + ပျက်စီးမှု သတင်းပို့ခြင်း + OONI Probe ပိုမိုကောင်းမွန်စေရန်အတွက် အက်ပ်သည် ကောင်းမွန်စွာ အလုပ်မလုပ်သည့်အခါ အမည်မသိ ပျက်စီးမှု အစီရင်ခံစာများကို စုဆောင်းလိုပါသည်။\n\nပျက်စီးမှု အစီရင်ခံစာများကို OONI ဖွံ့ဖြိုးတိုးတက်ရေး အဖွဲ့ထံ တင်သွင်းခြင်း လုပ်ငန်းတွင် သင် ပါဝင်လိုပါသလား။ + ဟုတ်တယ် + မဟုတ်ဘူး + နဂိုမူလ ဆက်တင်များ + ကျွန်ုပ်တို့ ကောက်ယူစုဆောင်း၍ ဖြန့်ဝေသည် - + နိုင်ငံကုဒ် (ဥပမာ - အီတလီအတွက် IT) + ကွန်ရက် သတင်းအချက်အလက် (အလိုအလျောက်စနစ် နံပတ်အပါအဝင်) + စမ်းသပ်ချိန်နှင့် ရက်စွဲ + သင်၏ IP လိပ်စာ သို့မဟုတ် အခြားသော ပုဂ္ဂိုလ်ရေးအရ ခွဲခြား သိမြင်နိုင်သော အချက်အလက်များကို ထုတ်ဝေခြင်းမပြုရန် ကျွန်ုပ်တို့ အကောင်းဆုံး လုပ်ဆောင်ပါသည်။ [OONI ၏ ဒေတာမူဝါဒ](https://ooni.org/about/data-policy/) တွင် ပိုမိုလေ့လာပါ။ + OONI Probe တိုးတက်စေရေးအတွက် ကျွန်ုပ်တို့အားကူညီနိုင်ရန် \"အိုကေ\" ကို နှိပ်၍ ပျက်စီးမှု အစီရင်ခံစာများကို မျှဝေနိုင်သည်။ + သွားကြစို့ + နဂိုမူလများကို ပြောင်းမည် + ဒက်ရှ်ဘုတ် + စမ်းမည် + အဖြေမရှိ + စမ်းမည် + နောက်ဆုံး စမ်းသပ်မှု - + ခန့်မှန်းထားသည် - + ဝဘ်ဆိုဒ်များ ရွေးချယ်ရန် + စမ်းသပ်နေသည် - + ခန့်မှန်း ကျန်ရှိချိန် - + %1$s စက္ကန့် + စမ်းသပ်မှုကို ပြင်ဆင်နေသည် + ETA တွက်ချက်ခြင်း + မှတ်တမ်း ပြမည် + မှတ်တမ်း ပိတ်မည် + စမ်းသပ်မှုကို ရပ်နေသည်... + လက်ရှိ စောင့်ဆိုင်းနေသော စမ်းသပ်မှုများကို အပြီးသတ်နေသည်၊ ကျေးဇူးပြု၍ စောင့်ပါ... + အသုံးပြုနေသော ပရောက်စီ + နောက်ထပ် ရွေးချယ်စရာများအတွက် ကတ်ကို နှိပ်ပါ + ~%1$ss + ဝဘ်ဆိုဒ်များ ပိတ်ဆို့ခြင်းကို စမ်းသပ်ပါ\n + OONI ၏ [ဝဘ်ချိတ်ဆက်မှု စမ်းသပ်ခြင်း](https://ooni.org/nettest/web-connectivity/) ကို အသုံးပြု၍ ဝဘ်ဆိုဒ်များအား ပိတ်ဆို့ထားခြင်းရှိ၊ မရှိ စစ်ဆေးပါ။\n\nစမ်းမည် ခလုတ်ကို နှိပ်တိုင်း Citizen Lab ၏ [ဂလိုဘယ်](https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) နှင့် [country-specific](https://github.com/citizenlab/test-lists/tree/master/lists) စမ်းသပ်မှု စာရင်းများမှ ကွဲပြားသော ဝဘ်ဆိုဒ်များကို သင် စမ်းသပ်ခြင်း ဖြစ်သည်။\n\nသင်ရွေးချယ်သည့် ဆိုဒ်များကို စမ်းသပ်ရန်၊ ဝဘ်ဆိုဒ်များ ရွေးချယ်မည် ခလုတ်ကို နှိပ်ပါ သို့မဟုတ် ဤကတ်၏ ဆက်တင်များမှ တစ်ဆင့် ဆိုဒ်များ၏ အမျိုးအစားများကို ရွေးချယ်ပါ။\n\nဤစမ်းသပ်မှုသည် ဝဘ်ဆိုက်များကို DNS ကစားခြင်း၊ TCP/IP ပိတ်ဆို့ခြင်း သို့မဟုတ် ပွင့်လင်းမြင်သာသော HTTP ပရောက်စီ ဖြင့် ပိတ်ဆို့ခြင်း ရှိ၊ မရှိ တိုင်းတာ စစ်ဆေးသည်။\nသင့် ရလဒ်များအား [OONI Explorer](https://explorer.ooni.org/world/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ပြန်ပေးပါမည်။ + OONI ၏ [ဝဘ်ချိတ်ဆက်မှုစမ်းသပ်ခြင်း](https://ooni.org/nettest/web-connectivity/) ကို အသုံးပြု၍ ဝဘ်ဆိုဒ်များအား ပိတ်ဆို့ထားခြင်းရှိ၊ မရှိ စစ်ဆေးပါ။\n\nCitizen Lab ၏ [ဂလိုဘယ်](https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) နှင့် [country-specific](https://github.com/citizenlab/test-lists/tree/master/lists) စမ်းသပ်မှု စာရင်းများ အပါအဝင် ဝဘ်ဆိုဒ်များကို စမ်းသပ်ရမည်။ \n\nဤစမ်းသပ်မှုသည် ဝဘ်ဆိုက်များကို DNS ဆော့ကစားခြင်း၊ TCP/IP ပိတ်ဆို့ခြင်း သို့မဟုတ် ပွင့်လင်းမြင်သာသော HTTP ပရောက်စီ ဖြင့် ပိတ်ဆို့ခြင်း ရှိ၊မရှိ တိုင်းတာသည်။\n\nသင့်ရလဒ်များအား [OONI Explorer](https://explorer.ooni.org/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ပြန်ပေးမည်။ + သင့် ကွန်ရက်အမြန်နှုန်းနှင့် စွမ်းဆောင်ရည်ကို စမ်းသပ်ပါ + [NDT] (https://ooni.org/nettest/ndt/) စမ်းသပ်မှုကို သုံး၍ သင်၏ကွန်ရက် အမြန်နှုန်းနှင့် စွမ်းဆောင်ရည်ကို တိုင်းတာပါ။\n\n[DASH] (https://ooni.org/nettest/dash/) စမ်းသပ်မှုကို သုံး၍ ဗီဒီယိုထုတ်လွှင့်ခြင်း စွမ်းဆောင်ရည်ကို တိုင်းတာပါ။\n\nဤစစ်ဆေးမှုများသည် သင့်ကွန်ရက် အမြန်နှုန်းပေါ်မူတည်၍ ဒေတာကို အသုံးပြုကြသည်။\n\nသင့် ရလဒ်များအား [OONI Explorer](https://explorer.ooni.org/world/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ဝေပါမည်။\n\nငြင်းဆိုချက် - ဤစစ်ဆေးမှုများသည် ပြင်ပ ဆာဗာများပေါ်တွင် အားကိုးပါသည်။ ထို့ကြောင့် သင်၏ IP လိပ်စာကို စုဆောင်းမည်မဟုတ်ကြောင်း ကျွန်ုပ်တို့ အာမ မခံနိုင်ပါ။ + ဤကတ်တွင် စမ်းသပ်မှုများကို လုပ်ဆောင်ခြင်းဖြင့် သင်သည် -\n\n\n- သင့် ကွန်ရက်၏ အမြန်နှုန်းနှင့် စွမ်းဆောင်ရည်ကို တိုင်းတာခြင်း ([NDT](https://ooni.org/nettest/ndt/) စမ်းသပ်မှု)\n- ဗီဒီယိုထုတ်လွှင့်ခြင်း စွမ်းဆောင်ရည်ကို တိုင်းတာခြင်း ([DASH](https://ooni.org/nettest/dash/) စမ်းသပ်မှု)\n\n- သင့်ကွန်ရက်တွင် [middlebox နည်းပညာများ](https://ooni.org/support/glossary/#middlebox) ရှိ၊ မရှိစစ်ဆေးပါ ([HTTP Invalid Request Line](https://ooni.org/nettest/http-invalid -request-line/) နှင့် [HTTP Header Field Manipulation](https://ooni.org/nettest/http-header-field-manipulation/) စမ်းသပ်မှုများ)\n\nဤစစ်ဆေးမှုများသည် သင့်ကွန်ရက် အမြန်နှုန်းပေါ်မူတည်၍ ဒေတာကို အသုံးပြုကြသည်။ \n\nသင်၏ စမ်းသပ်မှုရလဒ်များကို [OONI Explorer](https://explorer.ooni.org/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ပြန်မည်ဖြစ်ပါသည်။\n\n**ငြင်းဆိုချက် - ** အဆိုပါ [NDT](https://ooni.org/nettest/ndt/) နှင့် \n[DASH](https://ooni.org/nettest/dash/) စမ်းသပ်မှုများကို [Measurement Lab (M-Lab)](https://www.measurementlab.net/) \nမှ ပံ့ပိုးပေးသော ပြင်ပဆာဗာများက တဆင့် ဆောင်ရွက်ခြင်း ဖြစ်သည်။ ဤ စမ်းသပ်မှုများကို ဆောင်ရွက်လျှင် OONI Probe ဆက်တင်\nနှင့် မသက်ဆိုင်ဘဲ သင့် IP လိပ်စာအား M-Lab က ကောက်ယူကာ ထုတ်ပြန်မည်။ M-Lab ၏ [ကိုယ်ရေးလုံခြုံမှု ကြေညာချက်](https://www.measurementlab.net/privacy/) မှတဆင့် ၎င်း၏ ဒေတာစီမံခန့်ခွဲမှုအကြောင်းကို ပိုမိုသိရှိနိုင်သည်။ + သင့် ကွန်ရက်ရှိ middleboxes ကို ရှာဖွေရန် + အင်တာနက် ဝန်ဆောင်မှုပေးသူများသည် ကွန်ရက် ချိတ်ဆက်ခြင်းဆိုင်ရာ ရည်ရွယ်ချက်အမျိုးမျိုးအတွက် (caching ကဲ့သို့) အတွက် ကွန်ရက်သုံးပစ္စည်းများ (middleboxes) ကို မကြာခဏ အသုံးပြုကြသည်။ တခါတရံ ဤ middleboxes ကို အင်တာနက်ဆင်ဆာဖြတ်တောက်ခြင်းနှင့်/ သို့မဟုတ် စောင့်ကြည့်ခြင်းအား အကောင်အထည်ဖော်ရန် အသုံးပြုသည်။\n\nOONI ၏ [HTTP မဆီလျော်သော တောင်းဆိုမှုလိုင်း](https://ooni.org/nettest/http-invalid-request-line/) နှင့် [HTTP Header Field Manipulation](https://ooni.org/nettest/http-header-field-manipulation/) စမ်းသပ်မှုများကို သုံး၍ သင့်ကွန်ရက်အတွင်းရှိ middleboxes ကို ရှာနိုင်သည်။ \n\nသင့်ရလဒ်များအား [OONI Explorer](https://explorer.ooni.org/world/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ပြန်ပေးပါမည်။ + လက်ငင်း စာတိုပေးပို့ခြင်း အက်ပ်များ ပိတ်ဆို့ခြင်းအား စမ်းသပ်မည် + [WhatsApp](https://ooni.org/nettest/whatsapp/)၊ [Facebook Messenger](https://ooni.org/nettest/facebook-messenger/)၊ [Telegram](https://ooni.org/nettest/telegram/) နှင့် [Signal](https://ooni.org/nettest/signal) တို့ကို ပိတ်ဆို့ထားခြင်း ရှိ/မရှိ စစ်ဆေးမည်။\n\nသင့် ရလဒ်များအား [OONI Explorer](https://explorer.ooni.org/world/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ဝေပါမည်။ + ဆင်ဆာရှောင်တိမ်း ကိရိယာများကို ပိတ်ဆို့ စမ်းသပ်မည် + [Psiphon](https://ooni.org/nettest/psiphon/)၊ [Tor](https://ooni.org/nettest/tor/) သို့မဟုတ် [RiseupVPN](https://ooni.org/nettest/riseupvpn/) တို့ကို ပိတ်ဆို့ထားခြင်း ရှိ/မရှိ စစ်ဆေးရန်\nသင့် ရလဒ်များအား [OONI Explorer](https://explorer.ooni.org/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ပြန်ပေးပါမည်။ + စမ်းသပ်မှုအသစ်များကို လုပ်ဆောင်ရန် + OONI အဖွဲ့မှ ဖန်တီးထားသော အောက်ပါ စမ်းသပ်မှုအသစ်များကို လုပ်ဆောင်မည်\n%1$s\n\nသင့်ရလဒ်များကို [OONI Explorer](https://explorer.ooni.org/) နှင့် [OONI API](https://api.ooni.io/) တွင် ထုတ်ဝေပါမည်။ + အောက်ပါ စမ်းသပ်မှုများကို အလိုအ‌လျောက် စမ်းသပ်မှု၏ အစိတ်အပိုင်း အဖြစ်သာ ဆောင်ရွက်မည် - + ပယ်ဖျက်ထားသော စမ်းသပ်မှုများ\n + ဂစ်ဂါဘစ်/စက္ကန့် + မဂ္ဂါဘစ်/စက္ကန့် + ကီလိုဘစ်/စက္ကန့် + မီလီစက္ကန့် + မရရှိနိုင်ပါ + မသိ + စမ်းသပ်မှု ရလဒ်များ + စမ်းသပ်မှု ရလဒ်များ + စမ်းသပ်မှုများ + ကွန်ရက်များ + ဒေတာအသုံးပြုမှု + စမ်းသပ်မှုများ + စမ်းသပ်မှုအားလုံး + ဝဘ်ဆိုဒ်များ + Middleboxes + စွမ်းဆောင်ရည် + ချက်ခြင်း စာတိုပေးပို့ခြင်း\n + ရှောင်တိမ်းခြင်း + စမ်းသပ် လေ့လာနေဆဲ + စမ်းသပ်မှု မရှိသေးပါ။ စမ်းသပ်မှုတစ်ခုကို လုပ်ဆောင် ကြည့်လိုက်ပါ။ + %1$s ခု ပိတ်ဆို့ထားသည် + %1$s ခု ပိတ်ဆို့ထားသည် + %1$s ကြိမ် စမ်းသပ်ခဲ့သည် + %1$s ကြိမ် စမ်းသပ်ခဲ့သည် + စစ်ဆေး တွေ့ရှိခဲ့သည် + ရှာမတွေ့ပါ + မအောင်မြင်ပါ + %1$s ခု ပိတ်ဆို့ထားသည် + %1$s ခု ပိတ်ဆို့ထားသည် + %1$s အသုံးပြုနိုင်သည် + %1$s အသုံးပြုနိုင်သည် + %1$s ခု ပိတ်ဆို့ထားသည် + %1$s ခု ပိတ်ဆို့ထားသည် + %1$s ရရှိနိုင်သည် + %1$s ရရှိနိုင်သည် + မပြည့်စုံသော ရလဒ် + ပြဿနာ + တိုင်းတာမှုတွင် ပြဿနာ ရှိသည် + ရလဒ်များကို တင်ထားခြင်း မရှိပါ + နေ့စွဲ နှင့် အချိန် + ကွန်ရက် + နိုင်ငံ + ဒေတာအသုံးပြုမှု + စုစုပေါင်း လုပ်ဆောင်ချိန် + ဝိုင်ဖိုင် + မိုဘိုင်းဒေတာ + အင်တာနက်မရှိပါ + မအောင်မြင်ပါ + စမ်းသပ်ခဲ့သည် + စမ်းသပ်ခဲ့သည် + ပိတ်ဆို့ထားသည် + ပိတ်ဆို့ထားသည် + ဝဘ်ဆိုဒ် + ဝဘ်ဆိုဒ်များ + အသုံးပြုနိုင်သည် + အသုံးပြုနိုင်သည် + ဗီဒီယို + အရည်အသွေး + အပ်လုဒ် + ဒေါင်းလုဒ်လုပ်မည်\n + ပို့ပါ + ရှာတွေ့သည် + ရှာမတွေ့ပါ + မအောင်မြင်ပါ + စမ်းသပ်ခဲ့သည် + စမ်းသပ်ခဲ့သည် + ပိတ်ဆို့ထားသည် + ပိတ်ဆို့ထားသည် + အသုံးပြုနိုင်သည် + အသုံးပြုနိုင်သည် + အက်ပ် + အက်ပ်များ + စမ်းသပ်ခဲ့သည် + စမ်းသပ်ခဲ့သည် + ပိတ်ဆို့ထားသည် + ပိတ်ဆို့ထားသည် + အလုပ်လုပ်နေသည် + အလုပ်လုပ်နေသည် + ကိရိယာ + ကိရိယာများ + လုပ်ဆောင်ချိန် + နည်းစနစ် + ကြည့်ရှုမှု မှတ်တမ်း + ဒေတာ + Explorer URL ကို ကူးမည် + Explorer URL ကို မျှဝေမည်\n + Clipboard ထဲသို့ ကူးမည် + OONI Explorer တွင် ဖော်ပြရန် + မအောင်မြင်ပါ + သင်သည် ဤစမ်းသပ်မှုကို ထပ်မံ လုပ်ဆောင်နိုင်သည် + ထပ်ကြိုးစားပါ + ဤစမ်းသပ်မှု မည်သို့ အလုပ်လုပ်ပုံကို [ဤနေရာ](%1$s) တွင် လေ့လာပါ။ + အသုံးပြုနိုင်သည် + %1$s ကို အသုံးပြုနိုင်သည်။ + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + %1$s%2$s ဖြင့် ပိတ်ဆို့ထားဖွယ်ရှိသည်။\n\nမှတ်ချက် - မှားယွင်းသော အကောင်းမြင်မှုများ ဖြစ်နိုင်သည်။ [ဤနေရာတွင်](https://ooni.org/support/faq/#what-are-false-positives) ပိုမိုလေ့လာပါ။\n + ဆင်ဆာဖြတ်တောက်မှုအား ရှောင်တိမ်းခြင်း + **DNS ကစားခြင်း** + ** TCP/IP အခြေခံ ပိတ်ဆို့ခြင်း** + **HTTP ပိတ်ဆို့ခြင်း (ပိတ်ဆို့ထားသည့် စာမျက်နှာတစ်ခုကို မြင်ရနိုင်သည်)** + **HTTP ပိတ်ဆို့ခြင်း (HTTP တောင်းဆိုမှုများ မအောင်မြင်ပါ)** + မိုဘိုင်းအက်ပ် + အိုကေ + မအောင်မြင်ပါ + WhatsApp ဝဘ် + အိုကေ + မအောင်မြင်ပါ + မှတ်ပုံတင်မည်\n + အိုကေ + မအောင်မြင်ပါ + အလုပ်လုပ်နေသည် + ဤစမ်းသပ်မှုသည် WhatsApp ၏ အဆုံးမှတ်များ၊ မှတ်ပုံတင်ခြင်း ဝန်ဆောင်မှုနှင့် ဝဘ်အင်တာဖေ့စ် (web.whatsapp.com) တို့နှင့် အောင်မြင်စွာ ချိတ်ဆက် ထားသည်။ + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + WhatsApp ကို ပိတ်ဆို့ထားပုံ ရသည်။ + မိုဘိုင်းဖုန်း အက်ပ်\n + အိုကေ + မအောင်မြင်ပါ + တယ်လီဂရမ် ဝဘ် + အိုကေ + မအောင်မြင်ပါ + အလုပ်လုပ်နေသည် + ဤစမ်းသပ်မှုသည် Telegram ၏ အဆုံးမှတ်များနှင့် ဝဘ်အင်တာဖေ့စ် (web.telegram.org) နှင့် အောင်မြင်စွာ ချိတ်ဆက်ထားသည်။ + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + Telegram ကို ပိတ်ဆို့ထားပုံ ရသည်။ + TCP ချိတ်ဆက်မှုများ + အိုကေ + မအောင်မြင်ပါ + DNS ရှာဖွေမှုများ + အိုကေ + မအောင်မြင်ပါ + အလုပ်လုပ်နေသည် + ဤစမ်းသပ်မှုသည် Facebook ၏ endpoint များနှင့် အောင်မြင်စွာ ချိတ်ဆက်ပြီး Facebook IP လိပ်စာများအား ဖြေရှင်းခဲ့သည်။ + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + Facebook Messenger ကို ပိတ်ဆို့ထားပုံ ရသည်။ + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + Signal ကို ပိတ်ဆို့ထားပုံ ရသည်။ + အလုပ်လုပ်နေသည် + ဤစမ်းသပ်မှုသည် Signal ၏ endpoints နှင့် အောင်မြင်စွာ ချိတ်ဆက်ထားသည်။ + middleboxes ကို ရှာမတွေ့ပါ + ကျွန်ုပ်တို့၏ ဆာဗာများနှင့် ဆက်သွယ်သောအခါတွင် ကွန်ရက် ကွဲလွဲမှုကို မတွေ့ရှိရပါ။ + ကွန်ရက် ကစားခြင်း + ကျွန်ုပ်တို့၏ ထိန်းချုပ်မှုဆာဗာများကို ဆက်သွယ်သည့်အခါ ကွန်ရက် အသွားအလာကို ခြယ်လှယ်ထားသည်။\n\nဆိုလိုသည်မှာ ဆင်ဆာနှင့်/သို့မဟုတ် စောင့်ကြည့်ခြင်းအတွက် တာဝန်ရှိနိုင်သည့် middlebox တစ်ခု သင့်ကွန်ရက်တွင် ရှိနေနိုင်သည်ဟု ဆိုလိုသည်။ + middleboxes အား မတွေ့ရှိပါ + ကျွန်ုပ်တို့၏ ဆာဗာများနှင့် ဆက်သွယ်သောအခါတွင် ကွန်ရက် ကွဲလွဲမှုကို မတွေ့ရှိရပါ။ + ကွန်ရက်ကို လက်ဆော့ခြင်း + ကျွန်ုပ်တို့၏ ထိန်းချုပ်မှုဆာဗာများကို ဆက်သွယ်သည့်အခါ ကွန်ရက် အသွားအလာကို ခြယ်လှယ်ထားသည်။\n\nဆိုလိုသည်မှာ ဆင်ဆာနှင့်/သို့မဟုတ် စောင့်ကြည့်ခြင်းအတွက် တာဝန်ရှိနိုင်သည့် သင့် ကွန်ရက်တွင် middlebox တစ်ခု ရှိနေနိုင်သည်ဟု ဆိုလိုသည်။ + သင်ပို့ခဲ့သည် + သင် လက်ခံရရှိခဲ့သည် + အပ်လုဒ် + ဒေါင်းလုဒ်လုပ်မည် + Ping + ဆာဗာ + ပြန်ပို့မှုနှုန်း + ကောင်းစွာ အလုပ်မလုပ်ပါ + ပျမ်းမျှ Ping + Max Ping ခန့်မှန်းမှု + MSS + အချိန်ကုန်သွားသည် + ယာယီ သိမ်းစရာ မလိုဘဲ %1$s အထိ ထုတ်လွှင့် နိုင်ပါသည်။ + အလယ်အလတ် ဘစ်နှုန်း + Playout ကြန့်ကြာခြင်း + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + အလုပ်လုပ်နေသည် + [Psiphon](https://psiphon.ca/) ကို ပိတ်ဆို့ ထားပုံ ရသည်။\n + ကျွန်ုပ်တို့သည် Psiphon ချိတ်ဆက်မှု တစ်ခုကို အောင်မြင်စွာ စတင်နိုင်ခဲ့သည်။ ဆိုလိုသည်မှာ [Psiphon](https://psiphon.ca/) သည် အလုပ် လုပ်သင့်သည်။ + စတင်အလုပ်လုပ်သည့် အချိန် + %1$s စက္ကန့် + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + အလုပ်လုပ်နေသည် + [Tor](https://www.torproject.org/) ကို ပိတ်ဆို့ထားပုံ ရသည်။ + ကျွန်ုပ်တို့သည် နဂိုမူလ Tor bridges နှင့်/ သို့မဟုတ် Tor directory authorities ကို အောင်မြင်စွာ ချိတ်ဆက်နိုင်ခဲ့သည်။ ဆိုလိုသည်မှာ [Tor](https://www.torproject.org/) သည် သုံး၍ ရသင့်သည်။ + နဂိုမူလ Bridge များ + %1$s/%2$s အိုကေ + လုပ်ပိုင်ခွင့်ရှိသူများ လမ်းညွှန် + %1$s/%2$s အိုကေ + အမည် + လိပ်စာ + အမျိုးအစား + ချိတ်ဆက်မည် + ဒေတာဖလှယ်ခြင်း\n + ပိတ်ဆို့ခံရဖွယ် ရှိသည် + အလုပ်လုပ်နေသည် + [RiseupVPN](https://riseup.net/vpn) ကို ပိတ်ဆို့ထားပုံ ရသည်။ + ကျွန်ုပ်တို့အနေဖြင့် RiseupVPN\ ၏ bootstrap ဆာဗာနှင့် VPN gateways များကို အောင်မြင်စွာ ချိတ်ဆက်နိုင်ခဲ့သည်။ ဆိုလိုသည်မှာ [RiseupVPN](https://riseup.net/vpn) ကို သုံး၍ ရသင့်ပါသည်။ + Bootstrap ဆာဗာ + OpenVPN ချိတ်ဆက်မှုများ + ပေါင်းစပ် ချိတ်ဆက်မှုများ + ပိတ်ဆို့ထားသည် + %1$s ခု ပိတ်ဆို့ထားသည် + %1$s ခု ပိတ်ဆို့ထားသည် + အိုကေ + ဤစမ်းသပ်မှုသည် အစမ်းသဘော ဖြစ်သည်။ + သတင်း + သတင်း + အိုကေ + ဖျက်သိမ်းရန်​ + ထပ်မမေးပါနှင့် + ဖျက်မည် + ပြဿနာ + ထပ်ကြိုးစားပါ + ကောင်းပါပြီ + ရပါတယ်၊ ကျေးဇူးပါ + ယခု မဟုတ်ပါ + ဘာဖြစ်ဖြစ် စမ်းမည် + VPN ကို ပိတ်မည် + အမြဲတမ်း စမ်းမည် + စမ်းသပ်မှုကို မလုပ်ဆောင်နိုင်ပါ။ သင့် အင်တာနက် ချိတ်ဆက်မှုကို စစ်ဆေးပါ။\n + URL စာရင်းကို ဒေါင်းလုဒ်လုပ်၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။ + ကျေးဇူးပြု၍ စမ်းသပ်မှုအသစ် မစတင်မီ လက်ရှိလုပ်ဆောင်နေသော စမ်းသပ်မှုများ ပြီးဆုံးရန် စောင့်ပါ။ + အသိပေးချက်ဆိုင်ရာ ခွင့်ပြုချက်များ လိုအပ်သည်။ ကျေးဇူးပြု၍ သင့်ဖုန်း၏ ဆက်တင်များထဲတွင် ၎င်းတို့ကိုဖွင့်ပြီး သင်၏ OONI Probe အက်ပ်တွင် ၎င်းတို့ကို ဖွင့်ပါ။ + ဆက်တင်များသို့ သွားမည် + စမ်းသပ်မှုတစ်ခု လုပ်ဆောင်နေချိန်တွင် ဤမျက်နှာပြင်ကို ပိတ်ထားသည်။ + တိုင်းတာမှု ဒေတာအကြမ်းကို ဒေါင်းလုဒ်လုပ်ရန် သင်သည် အင်တာနက်နှင့် ချိတ်ဆက်ထားရန် လိုအပ်သည်။ + ရလဒ်များကို အပ်လုဒ်လုပ်ခြင်း မရှိပါ + သင့်စမ်းသပ်မှု ရလဒ်အချို့ကို OONI ဆာဗာများသို့ အပ်လုဒ် လုပ်ခြင်း မရှိသေးပါ။ OONI ၏ ဒေတာအစုသို့ ထည့်ပေးလိုပါက ၎င်းတို့ကို အပ်လုဒ် လုပ်ပါ။ + အပ်လုဒ် + %1$s ကို အပ်လုဒ်လုပ်နေသည်... + ဘက်ထရီ ပိုမိုကောင်းမွန်အောင် လုပ်ဆောင်ခြင်းမရှိဘဲ OONI Probe သည် စမ်းသပ်မှုအား အလိုအလျောက် မလည်ပတ်နိုင်ပါ။ ထပ်မံ ကြိုးစားလိုပါသလား။ + သင်၏ VPN ချိတ်ဆက်မှုကို ပိတ်ပါ။ + အကယ်၍ သင်သည် VPN ကိုဖွင့်ထားလျက် OONI Probeကို စမ်းသပ်လုပ်ဆောင်ပါက၊ စမ်းသပ်မှုရလဒ်များသည် နိုင်ငံမှားယွင်းကာ ထွက်ပေါ်လာနိုင်သည်။ သင်၏ VPN ချိတ်ဆက်မှုကို ပိတ်ပါ။ + အချို့သော တိုင်းတာမှုများသည် VPN ကို ကျော်၍ လုပ်ဆောင်ခဲ့သည်။ + VPN ကို ဖွင့်ထားလျက် တိုင်းတာမှုများအား အပ်လုဒ်လုပ်ပါက၊ စမ်းသပ်မှု ရလဒ်များသည် နိုင်ငံ မှားယွင်းကာ ထွက်ပေါ်လာနိုင်သည်။ + အပ်လုဒ်လုပ်ခြင်း အောင်မြင်သည် + ပျက်ကွက်မှု မှတ်တမ်းကို ပြသရန်\n + အင်တာနက် ဆင်ဆာဖြတ်ခြင်းဆိုင်ရာ အပ်ဒိတ်များကို ရယူပါ။ + အရေးပေါ် ဆင်ဆာဖြတ်တောက်မှု ဖြစ်ရပ်များအတွင်း OONI Probe စမ်းသပ်မှုများကို လုပ်ဆောင်ရန် စိတ်ဝင်စားပါသလား။ သင့် အနီးရှိ အင်တာနက်ဆင်ဆာ ဖြတ်တောက်မှုကို ကျွန်ုပ်တို့ ကြားရသည့်အခါ အချက်အလက် သတင်း လက်ခံရရှိရန် အသိပေးချက်များကို ဖွင့်ပါ။ + စစ်ဆေးမှုများ၏ တိကျမှုကို မြှင့်တင်ရန်၊ ကျွန်ုပ်တို့သည် GPS ခွင့်ပြုချက်များ လိုအပ်ပါသည်။ OONI သည် သင့် GPS အနေအထား၏ ခန့်မှန်းခြေကိုသာ စုဆောင်း ပါမည်။ + စမ်းသပ်မှုရလဒ်အားလုံးကို ဖျက်လိုပါသလား။ + ဤစမ်းသပ်မှုကို ဖျက်လိုပါသလား။ + ကျေးဇူးပြု၍ အနည်းဆုံး စမ်းသပ်မှုတစ်ခု ဖွင့်ပါ + ဤအကွက်တွင် ကိန်းဂဏန်းများကိုသာ ထည့်သွင်းပါ။ + စမ်းသပ်မှု ပြန်လုပ်ပါ + ဤစမ်းသပ်မှု မအောင်မြင်ပါ။ စမ်းသပ်မှုကို ပြန်လည် လုပ်ဆောင်လိုပါသလား။ + သင်သည် ဝဘ်ဆိုဒ် %1$s ကို ပြန်လည် စမ်းသပ် တော့မည်။ + စမ်းမည် + ဤဝဘ်စာမျက်နှာမှ ထွက်သည့်အခါ သင့် URL များကို သိမ်းဆည်းမည် မဟုတ်ပါ။ ဤစာမျက်နှာမှ ထွက်လိုသည်မှာ သေချာပါသလား။ + Manual Upload ကို ဖွင့်မလား။ + ဤဆက်တင်သည် သင့်အား မထုတ်ဝေရသေးသော တိုင်းတာမှုများကို ကိုယ်တိုင် ပြန်တင်ခွင့် ပြုသည်။ + ဖွင့်မည် + ရပါတယ်၊ ကျေးဇူးပါ + အပ်လုဒ်လုပ်ခြင်း မအောင်မြင်ပါ + ကျွန်ုပ်တို့သည် အတိုင်းအတာများကို %1$s/%2$s အပ်လုဒ်လုပ်၍ မရပါ။ မအောင်မြင်ခြင်း မှတ်တမ်းကို OONI developer များနှင့် မျှဝေထားပါသည်။ + မှတ်တမ်းဖိုင်ကို ရှာမတွေ့ပါ + ဆီလျော်သော URL များ မတွေ့ပါ + JSON မရှိပါ + ဤစမ်းသပ်မှုကို ရပ်လိုပါသလား။ + ဤအချိန်မှစ၍ လက်ရှိစမ်းသပ်မှုကို ရပ်မည် ဖြစ်သည်။ + စမ်းသပ်မှုများကို အလိုအလျောက် လုပ်ဆောင်လိုပါသလား။ + အလိုအလျောက် စမ်းသပ်ခြင်းကို ဖွင့်ခြင်းဖြင့် သင်သည် OONI တိုင်းတာမှုများကို ပုံမှန် ပံ့ပိုးပေးမည် ဖြစ်သည်။ + ကျေးဇူးပြု၍ အက်ပ်အား နောက်တွင် ဖွင့်ခွင့် ပြုပါ။ + ငါ့ကို နောက်မှ သတိပေးပါ + Clipboard ထဲသို့ ကူးမည် + အပ်လုဒ် မလုပ်ပါ + အပ်လုဒ် + အချို့ကို အပ်လုဒ်မလုပ်ခဲ့ပါ + အားလုံးကို အပ်လုဒ်လုပ်ပါ + ဝဘ်ဆိုဒ်များ + ချက်ခြင်း မက်ဆေ့ချ် + Middleboxes + စွမ်းဆောင်ရည် + ဆင်ဆာရှောင်တိမ်းခြင်း + စမ်းသပ် လေ့လာနေဆဲ + HTTP မဆီလျော်သော တောင်းဆိုမှုလိုင်း စမ်းသပ်မှု + HTTP Header Field Manipulation စမ်းသပ်မှု + ချိတ်ဆက်နိုင်စွမ်း စမ်းသပ်မှု + NDT မြန်နှုန်းစမ်းသပ်မှု + DASH ထုတ်လွှင့် စမ်းသပ်မှု + WhatsApp စမ်းသပ်မှု + Telegram စမ်းသပ်မှု + Facebook Messenger စမ်းသပ်မှု + Psiphon စမ်းသပ်မှု + Tor စမ်းသပ်မှု + RiseupVPN စမ်းသပ်မှု + Signal စမ်းသပ်မှု + ဆက်တင်များ + စမ်းသပ်မှု ကာလအတွက် သင် သတ်မှတ်ထားသော အချိန်ပမာဏသည် အလွန် နည်းသည်။ + OONI အကြောင်း + Open Observatory of Network Interference (OONI) သည် Tor ပရောဂျက် အောက်ရှိ လွတ်လပ်ဆော့ဖ်ဝဲလ် ပရောဂျက်တစ်ခု ဖြစ်ပြီး ကမ္ဘာတစ်ဝှမ်းရှိ အင်တာနက် ဆင်ဆာဖြတ်တောက်မှုများကို ပွင့်လင်းမြင်သာမှု ရှိစေရန် ရည်ရွယ်ပါသည်။ \n\n၂၀၁၂ ခုနှစ်မှ စတင်၍ OONI ၏ ကမ္ဘာ့ အသိုင်းအဝိုင်းသည် နိုင်ငံပေါင်း ၂၀၀ ကျော်တွင် ကွန်ရက်များကို တိုင်းတာနေပါသည်။ ဤတိုင်းတာမှုအချို့သည် အင်တာနက် ဆင်ဆာ ဖြတ်တောက်ခြင်း၏ သက်သေအဖြစ် တည်ရှိနေသည်။ + ပိုမိုလေ့လာရန် + ဘလော့ဂ် + အစီရင်ခံစာများ + OONI ဒေတာမူဝါဒ + အသိပေးချက်များ + ဖွင့်ထားသည် + စမ်းသပ်မှု ပြီးပါက အသိပေးမည် + သတင်းအသစ် ရယူရန် + အလိုအလျောက် စမ်းသပ်ခြင်း + စမ်းသပ်မှုများကို အလိုအလျောက် လုပ်ဆောင်ပါ + အလိုအလျောက်စမ်းသပ်မှု အရေအတွက် - %1$s။ + နောက်ဆုံး လုပ်ဆောင်ခဲ့သည့် အလိုအလျောက် စမ်းသပ်မှု - %1$s။ + WiFi နှင့် သာ + အားသွင်းနေစဉ်သာ + အလိုအလျောက် စမ်းသပ်ခြင်းကို ဖွင့်ထားခြင်းဖြင့် OONI Probe စမ်းသပ်မှုများသည် တစ်နေ့လျှင် အကြိမ်များစွာ အလိုအလျောက် လုပ်ဆောင်မည် ဖြစ်သည်။ သင်၏ စမ်းသပ်မှုရလဒ်များကို OONI Explorer တွင် အလိုအလျောက် ထုတ်ပြန်လိမ့်မည် - https://explorer.ooni.org/ \n\nအရေးကြီးသည် - သင့်စက်တွင် VPN ဖွင့်ထားပါက OONI Probe သည် စမ်းသပ်မှုများကို အလိုအလျောက် လုပ်ဆောင်မည် မဟုတ်ပါ။ အလိုအလျောက် OONI Probe စမ်းသပ်မှုအတွက် သင့်စက် VPN ကို ပိတ်ပါ။ ပိုမိုလေ့လာရန် - https://ooni.org/support/faq/#can-i-run-ooni-probe-over-a-vpn သို့ သွားပါ + မျှဝေခြင်း + အလိုအလျောက် ထုတ်ပြန်သော ရလဒ်များ + လူကိုယ်တိုင် ရလဒ် အပ်လုဒ်လုပ်ရန် + ကွန်ရက် အချက်အလက် ထည့်သွင်းရန် + ခန့်မှန်း geo-location ထည့်သွင်းရန် + ကျွန်ုပ်၏ IP လိပ်စာ ထည့်သွင်းရန် + နိုင်ငံကုဒ် ထည့်သွင်းရန် + တိုင်းတာမှုများကို မည်သည့်နိုင်ငံမှ ကောက်ယူနေကြောင်း သိရှိရန် ဤ သတင်းအချက်အလက် (ဥပမာ - အီတလီနိုင်ငံ အတွက် အတိုက်ကောက်စာလုံး IT) လိုအပ်သည်။ ဤရွေးချယ်မှုကို ပိတ်လိုသည်မှာ သေချာသလား။ + ရလဒ်များကို ထုတ်ပြန်ခြင်းဖြင့် သင်သည် ကွန်ရက်အား နှောင့်ယှက်မှုဆိုင်ရာ ပွင့်လင်းမြင်သာမှုကို တိုးမြင့်စေလျက် OONI အသိုင်းအဝိုင်းအား ကူညီပေးသည်။\n\nအင်တာနက်ဝန်ဆောင်မှုပေးသူများအား ခွဲခြားသတ်မှတ်ရန်အတွက် ကွန်ရက်သတင်းအချက်အလက်များ (ဥပမာ - အလိုအလျောက်စနစ် နံပါတ်) လိုအပ်ပါသည်။ + စမ်းသပ်ရွေးချယ်မှုများ + အထက်ဖော်ပြပါ စမ်းသပ်မှု ဆက်တင်များမှတစ်ဆင့် သင် ပြင်ဆင်သတ်မှတ်ထားသည့် အရာ (ဥပမာ - WhatsApp စစ်ဆေးမှုအား ပိတ်ခြင်း) သည် စမ်းသပ်မှုများကို ကိုယ်တိုင် လုပ်ဆောင်သည့် အပြင် စမ်းသပ်မှုများကို အလိုအလျောက် လည်ပတ်စေသည် (အလိုအလျောက် စမ်းသပ်မှုကို ဖွင့်ထားသောအခါ) တွင် သက်ရောက်မည် ဖြစ်သည်။ + တာရှည်စမ်းသပ်မှု + ရှေ့ဘက်တွင် အချိန်ကြာမြင့်သော စမ်းသပ်မှုများကို လုပ်ဆောင်မလား။ + ကိုယ်ရေးလုံခြုံမှု + ပျက်စီးမှု အစီရင်ခံစာများ ပေးပို့မည် + အဆင့်မြင့် + အမှောင်မုဒ် + အမှားပြင်ဆင်မှု မှတ်တမ်းများ\n + လတ်တလော မှတ်တမ်းများကို ကြည့်ပါ + ဘာသာစကား ဆက်တင် + ဘာသာစကား ရွေးမည်\n + domain fronting နည်းကို အမြဲသုံးရန်\n + OONI နောက်ခံ ပရောက်စီ + ကြားခံ အင်တာနက်စနစ် + မရှိ + Psiphon + အထူး ပရောက်စီ\n + အထူး ပရောက်စီ URL + အထူး ပရောက်စီ ပရိုတိုကော\n + ချိတ်ဆက်မှု + အထိုင်နေရာ အမည် + ပေါ့တ် + အထောက်အထားများ (မထည့်လည်းရသည်) + အသုံးပြုသူအမည် + စကားဝှက် + ဖန်တီးပြုပြင်သော ပရောက်စီပေါ်တွင် Psiphon ကိုသုံးပါ + OONI Probe ကို အသုံးပြု၍ မရနိုင်လျှင် ဖြစ်နိုင်ချေရှိသော ပိတ်ဆို့မှုကို ကျော်ဖြတ်နိုင်ရန် [Psiphon](https://psiphon.ca/) ကို ဖွင့်ပါ။ တနည်းအားဖြင့် သင်သည် စိတ်ကြိုက် ပရောက်စီကို သုံးနိုင်သည်။ + စမ်းသပ်ကာလကို ကန့်သတ်မည် + စမ်းသပ်မှုကာလ + စမ်းသပ်ရန် ဝဘ်ဆိုဒ် အမျိုးအစားများ + အမျိုးအစား %1$s ခု ကို ဖွင့်ထားသည် + တည်းဖြတ်မည် + အားလုံးကို မရွေးချယ်ရန်\n + အားလုံးကို ရွေးချယ်မည်\n + သိမ်းမည်\n + မသိမ်းဆည်းရသေးသော အပြောင်းအလဲများ + သင် ဖွင့်ထားသော အမျိုးအစားများအတွက် အပြောင်းအလဲအချို့ ပြုလုပ်ထားသည်။ ၎င်းတို့ကို သင် သိမ်းဆည်းလိုသလား။ + သိမ်းမည်\n + ဖယ်ရှားမည်\n + စမ်းသပ်မည့် ဝဘ်ဆိုဒ်များ ရွေးချယ်ရန် + URL + URL များ ထည့်ထားခြင်း မရှိပါ + စမ်းမည်\n + ဝဘ်ဆိုဒ်ထည့်ရန် + တန်းပလိတ်မှ တင်ရန် + စမ်းသပ်ထားသော ဝဘ်ဆိုဒ်အရေအတွက် (0 သည် ၀က်ဘ်ဆိုဒ်အားလုံးကို ဆိုလိုသည်) + WhatsApp ကို စမ်းသပ်မည်\n + Telegram ကို စမ်းသပ်မည်\n + Facebook Messenger ကို စမ်းသပ်မည်\n + Signal ကို စမ်းသပ်မည်\n + HTTP မဆီလျော်သော တောင်းဆိုမှု လိုင်းစမ်းသပ်မှုကို လုပ်ဆောင်ရန် + HTTP Header Field Manipulation စမ်းသပ်မှုကို လုပ်ဆောင်မည် + NDT မြန်နှုန်း စမ်းသပ်မှုကို လုပ်ဆောင်မည် + အလိုအလျောက် NDT ဆာဗာ ရွေးချယ်မှု + NDT ဆာဗာ လိပ်စာ + NDT ဆာဗာ ပေါ့တ် + DASH Streaming စမ်းသပ်မှုကို လုပ်ဆောင်ရန် + အလိုအလျောက် DASH ဆာဗာ ရွေးချယ်မှု + DASH ဆာဗာ + DASH ဆာဗာပေါ့တ် + Psiphon ကို စမ်းသပ်မည်\n + Tor ကို စမ်းသပ်မည်\n + RiseupVPN ကို စမ်းသပ်မည်\n + VPN အသုံးပြုနေချိန်တွင် သတိပေးပါ + ပံ့ပိုးကူညီရန် အီးမေးလ် ပို့ပါ + သင်ကြုံတွေ့နေရသော ပြဿနာကို ကျေးဇူးပြု၍ ဖော်ပြပါ - + အက်ပ်နှင့် iOS ဗားရှင်း အချက်အလက်များဖြင့် bugs@openobservatory.org သို့ အီးမေးလ် ပို့ပါ။ အောက်တွင်ပါရှိသော \"Clipboard ထဲသို့ ကူးမည်\" ကို နှိပ်၍ ကျွန်ုပ်တို့ အီးမေးလ်လိပ်စာကို ကူးပါ။ + လက်ရှိ အက်ပ် ဘာသာစကားသည် %1$s ဖြစ်သည် + ဘာသာစကား + သိုလှောင်မှုအား အသုံးပြုမှု + အသုံးပြုထားသော သိုလှောင်မှု + ဖျက်မည် + ရှင်းမည် + သင့်စက်မှ OONI တိုင်းတာမှုအားလုံးကို သင် ဖျက်တော့မည်။ အချက်အလက်များကို အပ်လုဒ် လုပ်ထားလျှင် ၎င်းတို့ကို [OONI Explorer](https://explorer.ooni.org) တွင် ဆက်လက် ရရှိနိုင်သည်။ + ပြီးသွားပါပြီ + စမ်းသပ်မှုကို ရပ်ပါ + mirror လုပ်ကြည့်ရန် + တင်နေပါသည်... + မမျှော်လင့်ထားသော ပြဿနာ ဖြစ်ပေါ်ခဲ့သည်။ ဤစာမျက်နှာကို ပြန်လည်စတင်ပါ။ + သင်သည် OONI Probe စမ်းသပ်မှု တစ်ခုကို လုပ်ဆောင်ပါတော့မည်။ + URL %1$s ခု + စမ်းသပ်မှု အမည် + စမ်းသပ်မှု အသေးစိတ် + စမ်းမည် + နောက်ဆုံးပေါ် မဟုတ် + ဤစမ်းသပ်မှု လုပ်ဆောင်ရန် OONI Probe ဗားရှင်းအသစ် လိုသည်။ + အပ်ဒိတ်လုပ်မည် + ပိတ်မည် + မဆီလျော်သော ကန့်သတ်ချက်ဘောင် + OONI Run လင့်ခ်သည် ပုံပျက်နေသည် သို့မဟုတ် သင့်အက်ပ်သည် ခေတ်မမီတော့ပါ။ + သင်သည် ဝဘ်ဆိုဒ်များထဲမှ ကျပန်းနမူနာဝဘ်ဆိုဒ်တခုကို စမ်းသပ်မည်။ + OONI Run လင့်ခ်ကို မနှိပ်မီ စမ်းသပ်မှု အပြီးသတ်ရန် စောင့်ပါ။ + မူးယစ်ဆေးဝါးနှင့် အရက် + ဘာသာတရား + ညစ်ညမ်းရုပ်ပုံ + ဆွဲဆောင်မှုရှိသော ဝတ်စားဆင်ယင်မှု + နိုင်ငံရေး ဝေဖန်မှု + လူ့အခွင့်အရေး ကိစ္စများ + ပတ်ဝန်းကျင် + အကြမ်းဖက်ဝါဒနှင့် စစ်သွေးကြွများ + အမုန်းစကား + သတင်းမီဒီယာ + လိင်ကိစ္စ ပညာပေး\n + ပြည်သူ့ကျန်းမာရေး + လောင်းကစားခြင်း + အင်တာနက်ဆင်ဆာ ရှောင်တိမ်းသည့် ကိရိယာများ + အွန်လိုင်း ချိန်းတွေ့ခြင်း + လူမှုကွန်ရက် + LGBTQ+ + File-sharing + ဟက်ကင်းကိရိယာများ + ဆက်သွယ်ရေးကိရိယာများ + မီဒီယာ ဝေမျှခြင်း + နေရာအထိုင်ချခြင်း နှင့် ဘလော့ဂ်တွင် စာရေးသားခြင်း + ရှာဖွေရေးအင်ဂျင်များ + ဂိမ်းဆော့ခြင်း + ယဉ်ကျေးမှု + ဘောဂဗေဒ + အစိုးရ + အီလက်ထရောနစ် ကူးသန်းရောင်းဝယ်ရေး + အကြောင်းအရာကို ထိန်းချုပ်မည် + အစိုးရ အဖွဲ့အစည်းများ + အထွေထွေ အကြောင်းအရာ + မူးယစ်ဆေးဝါးနှင့် အရက်သောစာ သုံးစွဲ၊ ရောင်းချခြင်း + ပံ့ပိုးကူညီမှုနှင့် ဝေဖန်ထောက်ပြမှု အပါအဝင် ဘာသာရေးဆိုင်ရာ ကိစ္စများ + ကြည်လင်ပြတ်သားသော ညစ်ညမ်းရုပ်ပုံများ နှင့် ကြည်လင်ပြတ်သားစွာ မဖော်ပြထားသော ညစ်ညမ်းရုပ်ပုံများ + အဝတ်အစား အနည်းငယ်သာ ဝတ်ဆင်ထားသော အမျိုးသမီးများ၏ ဆွဲဆောင်မှုရှိသော ဝတ်စားဆင်ယင်မှုနှင့် သရုပ်ဖော်ပုံ + ဝေဖန်ထောက်ပြစရာ နိုင်ငံရေးအမြင်များ + လူ့အခွင့်အရေးကိစ္စများ + သဘာဝ ပတ်ဝန်းကျင်ဆိုင်ရာ ကိစ္စရပ်များအပေါ် ဆွေးနွေးချက်များ + အကြမ်းဖက်ဝါဒ၊ အကြမ်းဖက် စစ်သွေးကြွ သို့မဟုတ် ခွဲထွက်ရေး လှုပ်ရှားမှုများ + လူမျိုး၊ လိင်၊ လိင်စိတ် သို့မဟုတ် အခြားသော ဝိသေသ လက္ခဏာများအပေါ် အခြေခံ၍ သီးခြားအုပ်စုများကို နှိမ့်ချခြင်း + အဓိက သတင်းဝဘ်ဆိုဒ်များ၊ ဒေသဆိုင်ရာ သတင်းများနှင့် လွတ်လပ်သော မီဒီယာများ + သန္ဓေတားဆေး၊ STDs၊ မုဒိမ်းမှု ကာကွယ်ရေးနှင့် ကိုယ်ဝန်ဖျက်ချခြင်း အပါအဝင် လိင်ပိုင်းဆိုင်ရာ ကျန်းမာရေး ကိစ္စများ + COVID-19၊ HIV/AIDS၊ Ebola ကဲ့သို့သော ပြည်သူ့ကျန်းမာရေး ပြဿနာများ + အွန်လိုင်းလောင်းကစားနှင့် အလောင်းအစား + အမည်ဝှက်ထားခြင်း၊ ဆင်ဆာဖြတ်တောက်ခြင်း ရှောင်တိမ်းခြင်းနှင့် ကုဒ်ဝှက်ခြင်း + အွန်လိုင်းချိန်းတွေ့ ဆိုဒ်များ + အွန်လိုင်း လူမှုကွန်ရက် ကိရိယာများနှင့် ပလက်ဖောင်းများ + (ညစ်ညမ်းရုပ်ပုံစာပေ မပါဝင်ဘဲ) သက်ဆိုင်ရာ ကိစ္စများကို ဆွေးနွေးသည့် LGBTQ+ အသိုင်းအဝိုင်း + cloud-based ဖိုင်သိုလှောင်မှု၊ torrents နှင့် P2P အပါအဝင် ဖိုင်မျှဝေခြင်း\n + ကွန်ပျူတာ လုံခြုံရေး ကိရိယာများနှင့် သတင်းများ + VoIP၊ စာတို ပေးပို့ခြင်းနှင့် ဝဘ်မေးလ် အပါအဝင် တစ်ဦးချင်းနှင့် အဖွဲ့လိုက် ဆက်သွယ်ရေး ကိရိယာများ + ဗီဒီယို၊ အသံနှင့် ဓာတ်ပုံ မျှဝေခြင်း + ဝဘ်ဆိုဒ် အထိုင်နေရာ၊ ဘလော့ဂ်ရေးသားခြင်း နှင့် အခြား အွန်လိုင်းထုတ်ဝေမှု + ရှာဖွေရေးအင်ဂျင်များနှင့် ပေါ်တယ်လ်များ + အွန်လိုင်း ဂိမ်းများနှင့် ဂိမ်းပလက်ဖောင်းများ (လောင်းကစားဆိုဒ်များ မပါ)\n + သမိုင်း၊ စာပေ၊ ဂီတ၊ ရုပ်ရှင်၊ သရော်စာနှင့် ဟာသများ အပါအဝင် ဖျော်ဖြေမှု\n + အထွေထွေ စီးပွားရေးဖွံ့ဖြိုးတိုးတက်မှုနှင့် ဆင်းရဲမွဲတေမှု + စစ်တပ်အပါအဝင် အစိုးရပိုင် ဝက်ဘ်ဆိုက်များ + စီးပွားဖြစ် ဝန်ဆောင်မှုများနှင့် ထုတ်ကုန်များ + ထိန်းချုပ်ရန် အသုံးပြုသည့် နူးညံ့သိမ်မွေ့သော သို့မဟုတ် အပြစ်ကင်းသော အကြောင်းအရာ + ကုလသမဂ္ဂ အပါအဝင် အစိုးရ အဖွဲ့အစည်းများ + အမျိုးအစား မခွဲခြားရသေးသော ဆိုဒ်များ + diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml new file mode 100644 index 000000000..d02b4fea4 --- /dev/null +++ b/app/src/main/res/values-vi/strings.xml @@ -0,0 +1,533 @@ + + + ONNI Probe + OONI Probe là gì? + Ứng dụng này để đo lường kiểm duyệt internet\n\nCác trang web và các ứng dụng mạng xã hội có bị chặn không? Kết nối internet của bạn có bị chậm bất thường không?\n\nHãy chạy ứng dụng OONI Probe để tìm hiểu! + Hiểu rồi + Chú ý! + Dữ liệu của OONI được công bố công khai, bao gồm thông tin về mạng của bạn. + Bất cứ ai giám sát hoạt động internet của bạn (ví dụ như chính phủ hay nhà mạng) sẽ biết bạn đang chạy OONI Probe. + Bạn có thể kiểm tra các trang web bị chặn (hoặc chọn bất cứ trang nào để kiểm tra) + Tôi hiểu + Tìm hiểu thêm + Đố Nhanh + Đúng + Sai + Quay lại + Tiếp tục + Câu hỏi 1/2 + Nếu có ai đó đang giám sát hoạt động internet của tôi, họ sẽ biết tôi đang chạy ứng dụng OONI Probe. + Cảnh báo + ONNI Probe không phải công cụ có tính bảo mật cá nhân. Bất cứ ai đang giám sát hoạt động internet của bạn sẽ biết được bạn đang chạy những phần mềm nào. + Câu hỏi 2/2 + Bất cứ khi nào tôi chạy ứng dụng OONI Probe, dữ liệu mạng mà tôi thu thập được sẽ được tự động công bố. + Cảnh báo + Để tăng tính minh bạch của việc kiểm duyệt internet, dữ liệu mạng của tất cả người dùng OONI Probe sẽ tự động được công bố (trừ khi họ tắt tính năng này khi cài đặt). + Kiểm tra tự động + Để đo lường sự kiểm duyệt internet hàng ngày, vui lòng bật chế độ kiểm tra tự động để OONI Probe có thể chạy các bài kiểm tra định kỳ\n\nĐừng lo, chúng tôi sẽ lưu ý đến việc sử dụng pin.\n\nBạn có thể tắt kiểm tra tự động ở phần cài đặt bất cứ lúc nào. + Báo cáo sự cố + Để cải thiện OONI Probe, chúng tôi muốn thu thập các báo cáo sự cố ẩn danh khi ứng dụng không hoạt động bình thường.\n\nBạn có muốn chọn gửi báo cáo sự cố cho nhóm phát triển OONI không? + + Không + Thiết đặt mặc định + Chúng tôi thu thập và công bố: + Mã quốc gia (ví dụ VN cho Việt Nam) + Thông tin mạng (bao gồm Số hệ thống tự trị - ASN) + Ngày Giờ kiểm tra + Chúng tôi luôn cố gắng để không công bố địa chỉ IP của bạn hay bất kỳ thông tin nào khác có thể nhận dạng cá nhân.\n\nTìm hiểu thêm thông qua [Chính sách dữ liệu của OONI] (https://ooni.org/about/data-policy/). + Khi nhấn \"OK\", bạn đồng ý chia sẻ báo cáo sự cố để giúp chúng tôi cải thiện OONI Probe. + Bắt đầu + Thay đổi mặc định + Bảng tóm tắt + Chạy + Không có + Chạy + Lần kiểm tra chót: + Ước lượng: + Chọn trang web + Đang chạy: + Ước lượng thời gian còn lại: + %1$s giây + Chuẩn bị kiểm tra + Tính toán ETA + Hiển thị Nhật ký + Đóng Nhật ký + Dừng kiểm tra + Đang hoàn tất các bài kiểm tra dở dang, vui lòng chờ đợi.... + Proxy đang sử dụng + Chạm vào thẻ để biết thêm chi tiết + ~%1$s + Kiểm tra việc chặn các trang web + Kiểm tra xem các trang web có bị chặn không bằng cách sử dụng [Kiểm tra Kết nối Web] của OONI (https://ooni.org/nettest/web-connectivity/).\n\nMỗi khi nhấn Chạy, bạn sẽ kiểm tra các trang web khác nhau từ danh sách [toàn cầu] của Citizen Lab (https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) và danh sách [quốc gia cụ thể] (https://github.com/citizenlab/test-lists/tree/master/lists).\n\nĐể chọn trang bạn muốn kiểm tra, hãy nhấn vào nút Chọn trang web hoặc chọn các danh mục trang web ở phần cài đặt.\n\nKiểm tra này cho biết các trang web có bị chặn bởi các phương thức sửa DNS trái phép, chặn TCP/IP hay bởi một proxy HTTP minh bạch không.\n\nKết quả của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/world/) và [OONI API] (https://api.ooni.io/). + Kiểm tra xem các trang web có bị chặn không bằng cách sử dụng [Kiểm tra Kết nối Web] của OONI (https://ooni.org/nettest/web-connectivity/).\n\nBạn sẽ kiểm tra các trang web khác nhau từ danh sách [toàn cầu] của Citizen Lab (https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) và danh sách [quốc gia cụ thể] (https://github.com/citizenlab/test-lists/tree/master/lists).\n\nKiểm tra này cho biết các trang web có bị chặn bởi các phương thức sửa DNS trái phép, chặn TCP / IP hay bởi một proxy HTTP minh bạch hay không.\n\nKết quả kiểm tra của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/) và [OONI API] (https://api.ooni.io/). + Kiểm tra tốc độ và hiệu suất mạng của bạn + Đo tốc độ và hiệu suất mạng của bạn bằng cách sử dụng kiểm tra [NDT] (https://ooni.org/nettest/ndt/).\n\nĐo hiệu suất phát trực tuyến video bằng bài kiểm tra [DASH] (https://ooni.org/nettest/dash/).\n\nCác bài kiểm tra này dùng dữ liệu tùy thuộc vào tốc độ mạng của bạn.\n\nKết quả kiểm tra của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/world/) và [OONI API] (https://api.ooni.io/).\n\nTuyên bố giới hạn trách nhiệm: Những kiểm tra này dựa trên máy chủ của bên thứ ba. Do đó, chúng tôi không thể đảm bảo rằng địa chỉ IP của bạn sẽ không bị thu thập. + Bằng cách chạy các bài kiểm tra này, bạn sẽ:\n\n- Đo tốc độ và hiệu suất mạng của bạn (kiểm tra [NDT] (https://ooni.org/nettest/ndt/))\n- Đo hiệu suất phát trực tuyến video (kiểm tra [DASH] (https://ooni.org/nettest/dash/))\n- Kiểm tra sự hiện diện của [công nghệ middlebox] (https://ooni.org/support/glossary/#middlebox) trên mạng của bạn qua các kiểm tra ([HTTP Invalid Request Line] (https://ooni.org/nettest/http-invalid -request-line /) và [HTTP Header Field Manipulation] (https://ooni.org/nettest/http-header-field-manipulation/) )\n\nCác bài kiểm tra này sử dụng dữ liệu tùy thuộc vào tốc độ mạng của bạn.\n\nKết quả kiểm tra của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/) và [OONI API] (https://api.ooni.io/).\n\n** Tuyên bố giới hạn trách nhiệm: ** Các bài kiểm tra [NDT] (https://ooni.org/nettest/ndt/) và [DASH] (https://ooni.org/nettest/dash/) được thực hiện trên các máy chủ của bên thứ ba được cung cấp bởi [Measurement Lab (M-Lab)] (https://www.measurementlab.net/). Nếu bạn chạy các bài kiểm tra này, M-Lab sẽ thu thập và công bố địa chỉ IP của bạn (cho mục đích nghiên cứu), cho dù cài đặt OONI Probe của bạn như thế nào. Tìm hiểu thêm về quản trị dữ liệu của M-Lab thông qua [tuyên bố về quyền riêng tư] (https://www.measurementlab.net/privacy/). + Phát hiện các middlebox trong mạng của bạn + Nhà mạng thường sử dụng các thiết bị mạng (middlebox) cho các mục đích mạng khác nhau (ví dụ như bộ nhớ đệm). Đôi khi những middlebox này được sử dụng để thực hiện kiểm duyệt và/ hoặc giám sát internet.\n\nTìm các middlebox trong mạng của bạn bằng cách kiểm tra [HTTP Invalid Request Line] của OONI (https://ooni.org/nettest/http-invalid-request-line/) và kiểm tra [HTTP Header Field Manipulation] (https://ooni.org/nettest/http-header-field-manipulation/) .\n\nKết quả kiểm tra của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/world/) và [OONI API] (https://api.ooni.io/). + Kiểm tra việc chặn các ứng dụng tin nhắn nhanh + Kiểm tra [WhatsApp] (https://ooni.org/nettest/whatsapp/), [Facebook Messenger] (https://ooni.org/nettest/facebook-messenger/), [Telegram] (https://ooni .org/nettest/telegram/) và [Signal] (https://ooni.org/nettest/signal) có bị chặn không.\n\nKết quả kiểm tra của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/world/) và [OONI API] (https://api.ooni.io/). + Kiểm tra việc chặn các công cụ vượt thoát kiểm duyệt + Kiểm tra [Psiphon] (https://ooni.org/nettest/psiphon/), [Tor] (https://ooni.org/nettest/tor/) hay [RiseupVPN] (https://ooni.org/nettest/roseupvpn/) có bị chặn không.\n\nKết quả kiểm tra của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/) và [OONI API] (https://api.ooni.io/). + Chạy các bài kiểm tra thử nghiệm mới + Chạy các bài kiểm tra thử nghiệm mới sau đây do nhóm OONI phát triển:\n%1$s\n\nKết quả kiểm tra của bạn sẽ được công bố trên [OONI Explorer] (https://explorer.ooni.org/) và [OONI API] (https://api.ooni.io/). + Các bài kiểm tra sau đây chỉ được chạy khi thực hiện kiểm tra tự động: + Kiểm tra bị tắt + Gbit/giây + Mbit/giây + kbit/giây + mili giây + Không có + Không rõ + Kết quả kiểm tra + Kết quả kiểm tra + Các bài kiểm tra + Mạng + Lượng dữ liệu dùng + Sàng lọc Kiểm tra + Tất cả kiểm tra + Trang web + Các middlebox + Hiệu suất + Tin Nhắn Nhanh + Vượt thoát kiểm duyệt + Thử nghiệm + Chưa có bài kiểm tra nào được chạy. Hãy chạy thử một bài kiểm tra! + %1$s đã bị chặn + %1$s đã bị chặn + %1$s đã được kiểm tra + %1$s đã được kiểm tra + Tìm thấy + Không tìm thấy + Thất bại + %1$s đã bị chặn + %1$s đã bị chặn + %1$s có thể truy cập + %1$s có thể truy cập + %1$s đã bị chặn + %1$s đã bị chặn + %1$s có sẵn + %1$s có sẵn + Kết quả chưa đầy đủ + Lỗi + Lỗi trong quá trình đo lường + Kết quả không được tải lên + Ngày & Giờ + Mạng + Quốc gia + Lượng dữ liệu dùng + Tổng cộng thời gian chạy + WiFi + Dữ liệu di động + Không có internet + Thất bại + Đã kiểm tra + Đã kiểm tra + Đã bị chặn + Đã bị chặn + Trang web + Trang web + Có thể truy cập + Có thể truy cập + Video + Chất lượng + Tải lên + Tải về + Ping + Tìm thấy + Không tìm thấy + Thất bại + Đã kiểm tra + Đã kiểm tra + Đã bị chặn + Đã bị chặn + Có thể truy cập + Có thể truy cập + Ứng dụng + Các ứng dụng + Đã kiểm tra + Đã kiểm tra + Đã bị chặn + Đã bị chặn + Đang hoạt động + Đang hoạt động + Công cụ + Công cụ + Thời gian chạy + Phương pháp + Xem Nhật ký + Dữ liệu + Sao chép URL của Explorer + Chia sẻ URL của Explorer + Sao chép vào Bảng ghi tạm + Hiển thị trong OONI Explorer + Thất bại + Bạn có thể thử chạy lại bài kiểm tra này + Thử lại + Tìm hiểu cách hoạt động của bài kiểm tra này [tại đây] (%1$s). + Có thể truy cập + %1$s có thể truy cập được + Có lẻ đã bị chặn + %1$s có lẻ bị chặn bởi %2$s.\n\nLưu ý: Kết quả này có thể không trúng (hiện tượng dương tính giả). Tìm hiểu thêm [tại đây] (https://ooni.org/support/faq/#what-are-false-pososystem) + Vượt thoát kiểm duyệt + **Sửa DNS trái phép** + ** Chặn dựa trên TCP/IP ** + ** Chặn HTTP (trang chặn được gửi ra) ** + ** Chặn HTTP (yêu cầu HTTP không thành công) ** + Ứng dụng trên điện thoại + OK + Thất bại + Trang web WhatsApp + OK + Thất bại + Đăng ký + OK + Thất bại + Đang hoạt động + Bài kiểm tra này đã kết nối thành công với các điểm cuối, dịch vụ đăng ký và giao diện web của WhatsApp (web.whatsapp.com). + Có lẻ bị chặn + WhatsApp dường như bị chặn. + Ứng dụng trên điện thoại + OK + Thất bại + Trang web Telegram + OK + Thất bại + Đang hoạt động + Bài kiểm tra này đã kết nối thành công với các điểm cuối và giao diện web của Telegram (web.telegram.org). + Có lẻ bị chặn + Telegram dường như bị chặn + Các kết nối TCP + OK + Thất bại + Tra cứu DNS + OK + Thất bại + Đang hoạt động + Bài kiểm tra này đã kết nối thành công với các điểm cuối của Facebook và lý giải đến các địa chỉ IP của Facebook. + Có lẻ bị chặn + Facebook Messenger dường như bị chặn. + Có lẻ bị chặn + Signal dường như bị chặn. + Đang hoạt động + Bài kiểm tra này đã kết nối thành công với các điểm cuối của Signal. + Không phát hiện middlebox + Không phát hiện bất thường trên mạng khi giao tiếp với máy chủ của chúng tôi. + Sửa đổi mạng trái phép + Lưu lượng mạng đã bị thay đổi trái phép khi liên lạc với các máy chủ kiểm soát của chúng tôi.\n\nĐiều này nghĩa là có thể có một middlebox trong mạng của bạn, có thể nhằm kiểm duyệt và/hoặc giám sát. + Không phát hiện middlebox + Không phát hiện bất thường trên mạng khi giao tiếp với máy chủ của chúng tôi. + Sửa đổi mạng trái phép + Lưu lượng mạng đã bị thay đổi trái phép khi liên lạc với các máy chủ kiểm soát của chúng tôi.\n\nĐiều này nghĩa là có thể có một middlebox trong mạng của bạn, có thể nhằm để kiểm duyệt và/hoặc giám sát. + Bạn đã gửi + Bạn đã nhận + Tải lên + Tải về + Ping + Máy chủ + Tỷ lệ truyền lại + Xảy ra lỗi + Ping trung bình + Ước lượng Ping tối đa + MSS + Thời gian chờ + Bạn có thể phát trực tiếp lên đến %1$s mà không bị gián đoạn + Tốc độ bit trung bình + Hoãn phát lại + Có lẻ bị chặn + Đang hoạt động + [Psiphon](https://psiphon.ca/) dường như bị chặn. + Chúng tôi đã khởi động thành công kết nối Psiphon. Điều này có nghĩa là [Psiphon] (https://psiphon.ca/) sẽ hoạt động. + Thời gian Khởi động + %1$s giây + Có lẻ bị chặn + Đang hoạt động + [Tor](https://www.torproject.org/) dường như bị chặn. + Chúng tôi đã kết nối thành công với cầu Tor mặc định và/hoặc danh bạ chính thức của Tor. Điều này có nghĩa là [Tor] (https://www.torproject.org/) sẽ hoạt động. + Cầu chuyển tiếp mặc định + %1$s/%2$s OK + Danh bạ Chính thức + %1$s/%2$s OK + Tên + Địa chỉ + Loại + Kết nối + Giao thức bắt tay + Có lẻ bị chặn + Đang hoạt động + [RiseupVPN](https://riseup.net/vpn) dường như bị chặn. + Chúng tôi đã kết nối thành công với máy chủ khởi động của RiseupVPN và các cổng VPN. Điều này có nghĩa là [RiseupVPN] (https://riseup.net/vpn) sẽ hoạt động. + Máy chủ Khởi động + Các kết nối OpenVPN + Các kết nối bắc cầu + Đã chặn + %1$s đã bị chặn + %1$s đã bị chặn + OK + Đây là bài kiểm tra thử nghiệm. + Cung cấp + Cung cấp + OK + Hủy + Không, đừng hỏi lại + Xóa + Lỗi + Thử lại + Rất tốt + Không, cảm ơn + Không phải bây giờ + Cứ chạy + Tắt VPN + Luôn chạy + Không thể chạy bài kiểm tra. Vui lòng kiểm tra lại kết nối internet của bạn. + Không thể tải danh sách URL. Vui lòng thử lại. + Vui lòng đợi các bài kiểm tra đang chạy kết thúc trước khi bắt đầu một bài kiểm tra mới. + Cần cho phép thông báo. Vui lòng bật thông báo trong Thiết Đặt của điện thoại sau đó bật thông báo trong ứng dụng OONI Probe của bạn. + Vào phần Thiết Đặt + Màn hình bị khóa khi bài kiểm tra đang chạy + Bạn cần kết nối với Internet để tải về các dữ liệu thô về đo lường + Kết quả không được tải lên + Một số kết quả kiểm tra của bạn chưa được tải lên máy chủ OONI. Nếu bạn muốn đóng góp vào bộ dữ liệu của OONI, vui lòng tải chúng lên. + Tải lên + Đang tải lên %1$s ... + OONI Probe không thể chạy tự động nếu không tối ưu hóa pin. Bạn có muốn thử lại không? + Vui lòng tắt kết nối VPN của bạn. + Nếu bạn chạy OONI Probe mà vẫn bật VPN, kết quả kiểm tra có thể đến từ quốc gia khác. Vui lòng tắt kết nối VPN của bạn. + Một số đo lường đã được thực hiện qua VPN. + Nếu bạn tải lên các đo lường được thực hiện khi bật VPN, kết quả kiểm tra có thể đến từ quốc gia khác. + Tải lên thành công + Hiển thị nhật ký lỗi + Nhận thông tin cập nhật về kiểm duyệt internet + Bạn quan tâm đến việc chạy kiểm tra OONI Probe trong các tình huống kiểm duyệt khẩn cấp? Bật thông báo để nhận tin nhắn khi chúng tôi biết có kiểm duyệt internet ở gần bạn. + Để cải thiện độ chính xác của các bài kiểm tra, chúng tôi cần có quyền truy cập GPS. OONI sẽ chỉ thu thập thông tin khái quát về vị trí GPS của bạn. + Bạn có muốn xóa tất cả các kết quả kiểm tra không? + Bạn có muốn xóa bài kiểm tra này không? + Vui lòng cho phép chạy ít nhất một bài kiểm tra + Xin chỉ điền số vào khung này. + Chạy lại bài kiểm tra + Bài kiểm tra này không thành công. Chạy lại bài kiểm tra? + Bạn chuẩn bị kiểm tra lại %1$s trang web. + Chạy + URL của bạn sẽ không được lưu khi bạn rời khỏi màn hình này. Bạn có chắc chắn muốn rời khỏi màn hình này không? + Bật cách Tự Tải Lên ? + Cài đặt này cho phép bạn tự mình tải lên các kết quả đo lường chưa được công bố. + Bật mở + Không, cảm ơn + Tải lên thất bại + Chúng tôi không thể tải lên %1$s / %2$s kết quả đo lường. Nhật ký lỗi đã được chia sẻ với các nhà phát triển OONI. + Không tìm thấy tập tin nhật ký + Không tìm thấy URL hợp lệ + JSON trống + Bạn có muốn tạm dừng bài kiểm tra này không? + Việc này sẽ làm gián đoạn bài kiểm tra từ thời điểm này. + Bạn có muốn chạy tự động các bài kiểm tra này không? + Bằng việc bật kiểm tra tự động, bạn sẽ đóng góp thường xuyên các kết quả đo lường cho OONI. + Vui lòng cho phép ứng dụng chạy trên nền sau. + Nhắc lại tôi sau + Đã sao chép vào clipboard + Chưa được tải lên + Tải lên + Một số chưa được tải lên + Tải lên tất cả + Trang web + Tin Nhắn Nhanh + Các middlebox + Hiệu suất + Vượt thoát kiểm duyệt + Thử nghiệm + Kiểm tra HTTP Invalid Request Line + Kiểm tra HTTP Header Field Manipulation + Kiểm tra Kết Nối Web + Kiểm tra tốc độ NDT + Kiểm tra phát trực tuyến DASH + Kiểm tra WhatsApp + Kiểm tra Telegram + Kiểm tra Facebook Messenger + Kiểm tra Psiphon + Kiểm tra Tor + Kiểm tra RiseupVPN + Kiểm tra Signal + Thiết đặt + Thời lượng bạn chọn cho quá trình kiểm tra quá ngắn, + Giới thiệu về OONI + Đài Quan Sát Mở về Can Thiệp Mạng (OONI) là một dự án phần mềm miễn phí thuộc Dự án Tor nhằm mục đích tăng cường tính minh bạch của việc kiểm duyệt internet trên toàn thế giới.\n\nKể từ năm 2012, cộng đồng OONI toàn cầu đã mở rộng mạng lưới tại hơn 200 quốc gia. Một số các kết quả đo lường này là bằng chứng về sự kiểm duyệt internet. + Tìm hiểu thêm + Blog + Báo cáo + Chính sách Dữ liệu của OONI + Thông báo + Bật lên + Thông báo khi bài kiểm tra hoàn tất + Bài đăng mới + Kiểm tra tự động + Chạy kiểm tra tự động + Số lượng các bài kiểm tra tự động: %1$s. + Lần kiểm tra tự động gần đây nhất: %1$s. + Chỉ khi có WiFi + Chỉ khi đang sạc + Khi bật kiểm tra tự động, các bài kiểm tra OONI Probe sẽ tự động chạy nhiều lần mỗi ngày. Kết quả kiểm tra của bạn sẽ tự động được xuất bản trên OONI Explorer: https://explorer.ooni.org/\n\nQuan trọng: Nếu bạn bật VPN, OONI Probe sẽ không tự động chạy kiểm tra. Vui lòng tắt VPN của bạn để kiểm tra OONI Probe tự động. Tìm hiểu thêm: https://ooni.org/support/faq/#can-i-run-ooni-probe-over-a-vpn + Chia sẻ + Tự động công bố các kết quả + Tự Tải Lên Kết Quả + Bao gồm thông tin mạng + Bao gồm vị trí địa lý ước lượng + Bao gồm địa chỉ IP của tôi + Bao gồm Mã quốc gia + Thông tin này (ví dụ: VN là viết tắt của Việt Nam) cần có để xác định quốc gia mà các đo lường được thu thập. Bạn có chắc chắn muốn tắt tùy chọn này không? + Bằng việc công bố kết quả, bạn đang góp phần tăng cường tính minh bạch trong can thiệp mạng và hỗ trợ cộng đồng OONI.\n\nThông tin mạng (ví dụ Số hệ thống tự trị - ASN) là bắt buộc để xác định Nhà cung cấp mạng + Tùy chọn kiểm tra + Những gì bạn cấu hình thông qua thiết đặt kiểm tra ở trên (ví dụ: tắt kiểm tra WhatsApp) sẽ áp dụng cho các bài kiểm tra chạy theo cách thủ công, cũng như các bài kiểm tra chạy tự động (khi kiểm tra tự động được bật). + Bài kiểm tra dài + Chạy bài kiểm tra dài ở nền trước? + Riêng tư + Gửi báo cáo sự cố + Nâng cao + Màn hình tối + Nhật ký gỡ lỗi + Xem nhật kí gần đây + Thiết đặt Ngôn ngữ + Chọn Ngôn Ngữ + Luôn sử dụng domain fronting + Backend proxy của OONI + Proxy + Không có + Psiphon + Proxy tùy chỉnh + URL Proxy tùy chỉnh + Giao thức proxy tùy chỉnh + Kết nối + Tên máy chủ + Cổng + Thông tin xác thực (tùy chọn) + Tên đăng nhập + Mật khẩu + Sử dụng Psiphon thay cho proxy tùy chỉnh + Bạn không thể sử dụng OONI Probe? Hãy thử bật [Psiphon] (https://psiphon.ca/) để vượt qua kiểm duyệt lên OONI Probe. Hoặc, bạn có thể sử dụng proxy tùy chỉnh. + Giới hạn thời lượng kiểm tra + Thời lượng kiểm tra + Thể loại web để kiểm tra + %1$s thể loại đã bật mở + Chỉnh sửa + Bỏ chọn tất cả + Chọn Tất cả + Lưu + Thay đổi chưa được lưu + Bạn đã thực hiện một số thay đổi đối với các thể loại đã bật mở. Bạn có muốn lưu lại không? + Lưu + Hủy bỏ + Chọn các trang web để kiểm tra + URL + Không có URL nào được nhập + Chạy + Thêm trang web + Nạp vào từ biểu mẫu + Số lượng trang web được thử nghiệm (0 có nghĩa là tất cả) + Kiểm tra WhatsApp + Kiểm tra Telegram + Kiểm tra Facebook Messenger + Kiểm tra Signal + Chạy kiểm tra HTTP Invalid Request Line + Chạy kiểm tra HTTP Header Field Manipulation + Chạy kiểm tra tốc độ NDT + Lựa chọn máy chủ NDT tự động + Địa chỉ máy chủ NDT + Cổng máy chủ NDT + Chạy kiểm tra phát trực tuyến DASH + Tự động chọn máy chủ DASH + Máy chủ DASH + Cổng máy chủ DASH + Kiểm tra Psiphon + Kiểm tra Tor + Kiểm tra RiseupVPN + Cảnh báo khi VPN được sử dụng + Gửi email đến hỗ trợ + Vui lòng mô tả vấn đề bạn đang gặp phải: + Vui lòng gửi email đến bugs@openobservatory.org kèm theo thông tin về ứng dụng và phiên bản iOS. Nhấn vào \"Sao chép vào Bảng ghi tạm\" bên dưới để sao chép địa chỉ email của chúng tôi. + Ngôn ngữ hiện tại của ứng dụng là %1$s + Ngôn ngữ + Lượng lưu trữ sử dụng + Lượng lưu trữ đã dùng + Xóa + Xoá + Bạn chuẩn bị xóa tất cả các kết quả đo lường OONI khỏi thiết bị của mình. Nếu được tải lên, những kết quả này sẽ có trên [OONI Explorer] (https://explorer.ooni.org) + Đã chạy xong + Dừng kiểm tra + Thử đối xứng + Đang nạp... + Đã xảy ra lỗi bất ngờ. Vui lòng nạp lại trang này. + Bạn chuẩn bị chạy bài kiểm tra OONI Probe. + %1$s URL + Tên bài kiểm tra + Thông tin về bài kiểm tra + Chạy + Quá hạn + Bạn cần cài đặt phiên bản mới hơn của OONI Probe để chạy bài kiểm tra này. + Cập nhật + Đóng + Thông số không hợp lệ + Liên kết chạy OONI không đúng định dạng hoặc ứng dụng của bạn chưa được cập nhật. + Bạn sẽ kiểm tra một số trang web ngẫu nhiên. + Vui lòng đợi cho bài kiểm tra hoàn thành trước khi nhấn vào liên kết chạy OONI. + Ma túy và Rượu + Tôn giáo + Nội dung khiêu dâm + Trang phục khêu gợi + Phê bình chính trị + Các vấn đề về nhân quyền + Môi trường + Chủ nghĩa khủng bố và các phần tử quá khích + Phát ngôn thù hận + Truyền thông tin tức + Giáo dục giới tính + Y tế công cộng + Cờ bạc + Công cụ vượt thoát kiểm duyệt + Hẹn hò trực tuyến + Mạng xã hội + LGBTQ+ + Chia sẻ tập tin + Công cụ lấy cắp dữ liệu + Công cụ truyền thông + Chia sẻ truyền thông + Dịch vụ lưu trữ web và viết blog + Công cụ tìm kiếm + Game + Văn hóa + Kinh tế + Chính phủ + Thương mại điện tử + Nội dung kiểm soát + Tổ chức liên chính phủ + Nội dung khác + Sử dụng và mua bán ma túy và rượu + Các vấn đề tôn giáo, cả ủng hộ và phản biện + Nội dung khiêu dâm nhẹ và mạnh bạo + Trang phục khêu gợi và hình ảnh phụ nữ mặc quần áo hở hang + Quan điểm chính trị phê phán + Các vấn đề về nhân quyền + Thảo luận về các vấn đề môi trường + Chủ nghĩa khủng bố, các phần tử bạo lực hoặc phong trào ly khai + Phê phán các nhóm về chủng tộc, giới tính, xu hướng tính dục hoặc các đặc điểm khác + Các trang web tin tức lớn, các hãng tin tức khu vực và các phương tiện truyền thông độc lập + Các vấn đề sức khỏe tình dục bao gồm tránh thai, các bệnh lây qua đường tình dục, ngăn ngừa hiếp dâm và nạo phá thai + Các vấn đề về y tế công cộng, như COVID-19, HIV/AIDS, Ebola + Cờ bạc và cá độ trực truyến + Ẩn danh, vượt thoát kiểm duyệt và mã hóa + Các trang hẹn hò trực tuyến + Các nền tảng và công cụ mạng xã hội trực tuyến + Cộng đồng LGBTQ + thảo luận về các vấn đề liên quan (trừ nội dung khiêu dâm) + Chia sẻ tập tin bao gồm dữ liệu lưu trữ điện toán đám mây, torrent và P2P + Công cụ bảo mật máy tính và tin tức + Công cụ giao tiếp cá nhân và nhóm bao gồm VoIP, nhắn tin và webmail + Chia sẻ video, âm thanh và hình ảnh + Lưu trữ web, viết blog và xuất bản trực tuyến khác + Công cụ tìm kiếm và cổng thông tin + Trò chơi trực tuyến và các nền tảng trò chơi (không bao gồm các trang web cờ bạc) + Giải trí, bao gồm lịch sử, văn học, âm nhạc, phim ảnh, châm biếm và hài + Tình hình chung về phát triển kinh tế và nghèo đói + Các trang web do chính phủ quản lý, bao gồm quân đội + Các sản phẩm và dịch vụ thương mại + Nội dung ôn hoà hoặc vô hại được sử dụng để kiểm soát + Các tổ chức liên chính phủ bao gồm Liên Hợp quốc + Các trang web chưa được phân loại + diff --git a/app/src/main/res/values/untraslatable.xml b/app/src/main/res/values/untraslatable.xml index 1201a1629..8e52cf58e 100644 --- a/app/src/main/res/values/untraslatable.xml +++ b/app/src/main/res/values/untraslatable.xml @@ -282,6 +282,8 @@ Kiswahili ไทย Türkçe + Tiếng Việt + မြန်မာ auto @@ -308,6 +310,8 @@ sw th tr + vi + my org.openobservatory.ooniprobe.activity.InfoActivity org.openobservatory.ooniprobe.activity.ProxyActivity diff --git a/app/src/main/res/xml/preferences_global.xml b/app/src/main/res/xml/preferences_global.xml index 8b93cd241..c973e7ed1 100644 --- a/app/src/main/res/xml/preferences_global.xml +++ b/app/src/main/res/xml/preferences_global.xml @@ -348,7 +348,9 @@ android:icon="@drawable/proxy" android:key="@string/ooni_backend_proxy" android:title="@string/Settings_Proxy_Label"> - + - + - + diff --git a/app/src/test/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuiteTest.java b/app/src/test/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuiteTest.java index f7c53c482..b220e7234 100644 --- a/app/src/test/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuiteTest.java +++ b/app/src/test/java/org/openobservatory/ooniprobe/domain/GenerateAutoRunServiceSuiteTest.java @@ -31,10 +31,7 @@ public class GenerateAutoRunServiceSuiteTest extends RobolectricAbstractTest { // Mocks - OONICheckInInfoWebConnectivity webConnectivityMock = mock(OONICheckInInfoWebConnectivity.class); PreferenceManager preferenceManagerMock = mock(PreferenceManager.class); - OONICheckInConfig ooniCheckConfigMock = mock(OONICheckInConfig.class); - OONICheckInResults ooniResultsMock = mock(OONICheckInResults.class); OONISession ooniSessionMock = mock(OONISession.class); // Engine && UseCase @@ -52,73 +49,19 @@ public void setUp() { } @Test - public void shouldNotStartTest() { + public void generateSuite() { // Act - AbstractSuite suite = generateSuite.generate(ooniCheckConfigMock); - - // Assert - Assert.assertNull(suite); - } - - @Test - public void generateSuite() throws Exception { - // Arrange - ArrayList suiteUrls = getTestUrls(); - - when(preferenceManagerMock.getEnabledCategoryArr()).thenReturn(new ArrayList() { - { - add("ALDR"); - add("REL"); - add("PORN"); - add("PROV"); - add("POLR"); - add("HUMR"); - add("ENV"); - } - }); - - when(webConnectivityMock.getUrls()).thenReturn(suiteUrls); - when(ooniResultsMock.getWebConnectivity()).thenReturn(webConnectivityMock); - when(ooniSessionMock.checkIn(any(), any())).thenReturn(ooniResultsMock); - - // Act - AbstractSuite suite = generateSuite.generate(ooniCheckConfigMock); + AbstractSuite suite = generateSuite.generate(); // Assert Assert.assertNotNull(suite); - verify(preferenceManagerMock, times(1)).updateAutorunDate(); - verify(preferenceManagerMock, times(1)).incrementAutorun(); Assert.assertEquals(1, suite.getTestList(preferenceManagerMock).length); AbstractTest webTest = suite.getTestList(preferenceManagerMock)[0]; Assert.assertEquals("web_connectivity", webTest.getName()); - Assert.assertEquals(suiteUrls.size(), webTest.getInputs().size()); - - for (int i = 0; i < webTest.getInputs().size(); i++) { - Assert.assertEquals( webTest.getInputs().get(i), suiteUrls.get(i).getUrl()); - } - } - - private ArrayList getTestUrls() { - Faker faker = new Faker(); - - OONIURLInfo url1 = mock(OONIURLInfo.class); - when(url1.getUrl()).thenReturn(faker.internet.url()); - - OONIURLInfo url2 = mock(OONIURLInfo.class); - when(url1.getUrl()).thenReturn(faker.internet.url()); - - OONIURLInfo url3 = mock(OONIURLInfo.class); - when(url1.getUrl()).thenReturn(faker.internet.url()); + Assert.assertNull(webTest.getInputs()); - return new ArrayList(){ - { - add(url1); - add(url2); - add(url3); - } - }; } } \ No newline at end of file diff --git a/app/src/test/java/org/openobservatory/ooniprobe/domain/GenerateTestServiceSuiteAutoRun.java b/app/src/test/java/org/openobservatory/ooniprobe/domain/GenerateTestServiceSuiteAutoRun.java deleted file mode 100644 index 705fe657e..000000000 --- a/app/src/test/java/org/openobservatory/ooniprobe/domain/GenerateTestServiceSuiteAutoRun.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.openobservatory.ooniprobe.domain; - -import androidx.test.filters.SmallTest; - -import org.junit.Assert; -import org.junit.Test; -import org.openobservatory.engine.OONICheckInConfig; -import org.openobservatory.engine.OONICheckInResults; -import org.openobservatory.engine.OONICheckInResults.OONICheckInInfoWebConnectivity; -import org.openobservatory.engine.OONISession; -import org.openobservatory.engine.OONIURLInfo; -import org.openobservatory.ooniprobe.RobolectricAbstractTest; -import org.openobservatory.ooniprobe.common.PreferenceManager; -import org.openobservatory.ooniprobe.engine.TestEngineInterface; -import org.openobservatory.ooniprobe.test.EngineInterface; -import org.openobservatory.ooniprobe.test.EngineProvider; -import org.openobservatory.ooniprobe.test.suite.AbstractSuite; -import org.openobservatory.ooniprobe.test.test.AbstractTest; - -import java.util.ArrayList; - -import io.bloco.faker.Faker; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@SmallTest -public class GenerateTestServiceSuiteAutoRun extends RobolectricAbstractTest { - - // Mocks - OONICheckInInfoWebConnectivity webConnectivityMock = mock(OONICheckInInfoWebConnectivity.class); - PreferenceManager preferenceManagerMock = mock(PreferenceManager.class); - OONICheckInConfig ooniCheckConfigMock = mock(OONICheckInConfig.class); - OONICheckInResults ooniResultsMock = mock(OONICheckInResults.class); - OONISession ooniSessionMock = mock(OONISession.class); - - // Engine && UseCase - EngineInterface mockedEngine = new TestEngineInterface(ooniSessionMock); - GenerateAutoRunServiceSuite generateSuite; - - @Override - public void setUp() { - super.setUp(); - generateSuite = new GenerateAutoRunServiceSuite(a, preferenceManagerMock); - EngineProvider.engineInterface = mockedEngine; - - when(preferenceManagerMock.testWifiOnly()).thenReturn(true); - when(preferenceManagerMock.testChargingOnly()).thenReturn(true); - } - - @Test - public void shouldNotStartTest() { - // Act - AbstractSuite suite = generateSuite.generate(ooniCheckConfigMock); - - // Assert - Assert.assertNull(suite); - } - - @Test - public void generateSuite() throws Exception { - // Arrange - ArrayList suiteUrls = getTestUrls(); - - when(preferenceManagerMock.getEnabledCategoryArr()).thenReturn(new ArrayList() { - { - add("ALDR"); - add("REL"); - add("PORN"); - add("PROV"); - add("POLR"); - add("HUMR"); - add("ENV"); - } - }); - - when(webConnectivityMock.getUrls()).thenReturn(suiteUrls); - when(ooniResultsMock.getWebConnectivity()).thenReturn(webConnectivityMock); - when(ooniSessionMock.checkIn(any(), any())).thenReturn(ooniResultsMock); - - // Act - AbstractSuite suite = generateSuite.generate(ooniCheckConfigMock); - - // Assert - Assert.assertNotNull(suite); - Assert.assertEquals(1, suite.getTestList(preferenceManagerMock).length); - - AbstractTest webTest = suite.getTestList(preferenceManagerMock)[0]; - - Assert.assertEquals("web_connectivity", webTest.getName()); - Assert.assertEquals(suiteUrls.size(), webTest.getInputs().size()); - - for (int i = 0; i < webTest.getInputs().size(); i++) { - Assert.assertEquals(webTest.getInputs().get(i), suiteUrls.get(i).getUrl()); - } - } - - private ArrayList getTestUrls() { - Faker faker = new Faker(); - - OONIURLInfo url1 = mock(OONIURLInfo.class); - when(url1.getUrl()).thenReturn(faker.internet.url()); - - OONIURLInfo url2 = mock(OONIURLInfo.class); - when(url1.getUrl()).thenReturn(faker.internet.url()); - - OONIURLInfo url3 = mock(OONIURLInfo.class); - when(url1.getUrl()).thenReturn(faker.internet.url()); - - return new ArrayList() { - { - add(url1); - add(url2); - add(url3); - } - }; - } - -} \ No newline at end of file diff --git a/app/src/test/java/org/openobservatory/ooniprobe/test/TestAsyncTaskTest.java b/app/src/test/java/org/openobservatory/ooniprobe/test/TestAsyncTaskTest.java index 56816f49e..0e8c69813 100644 --- a/app/src/test/java/org/openobservatory/ooniprobe/test/TestAsyncTaskTest.java +++ b/app/src/test/java/org/openobservatory/ooniprobe/test/TestAsyncTaskTest.java @@ -161,7 +161,7 @@ public void runTest_withProgress() { AbstractTest test = mock(AbstractTest.class); when(mockedSuite.getTestList(any())).thenReturn(new AbstractTest[]{test}); - TestAsyncTask task = new TestAsyncTask(a, suiteList, false); + TestAsyncTask task = new TestAsyncTask(a, suiteList, false,false); // Act task.execute(); @@ -189,14 +189,14 @@ public void runTest_withError() { when(mockedSuite.getTestList(any())).thenReturn(new AbstractTest[]{test}); doThrow(new RuntimeException("")).when(test).run(any(), any(), any(), any(), any(), anyInt(), any()); - TestAsyncTask task = new TestAsyncTask(a, suiteList,false); + TestAsyncTask task = new TestAsyncTask(a, suiteList,false,false); // Act task.execute(); idleTaskUntilFinished(task); // Assert - verify(runService).stopSelf(); + verify(runService).stopSelf(); } @Test @@ -209,7 +209,7 @@ public void runTest_interrupt() { when(mockedSuite.getTestList(any())).thenReturn(new AbstractTest[]{test}); when(test.canInterrupt()).thenReturn(true); - TestAsyncTask task = new TestAsyncTask(a, suiteList, false); + TestAsyncTask task = new TestAsyncTask(a, suiteList, false,false); // Act task.execute(); diff --git a/applogger/build.gradle b/applogger/build.gradle index 2726a7647..424233927 100644 --- a/applogger/build.gradle +++ b/applogger/build.gradle @@ -4,11 +4,11 @@ plugins { } android { - compileSdk 31 + compileSdk libs.versions.compileSdk.get().toInteger() defaultConfig { - minSdk 16 - targetSdk 31 + minSdk libs.versions.minSdk.get().toInteger() + targetSdk libs.versions.targetSdk.get().toInteger() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -32,5 +32,5 @@ android { } dependencies { - testImplementation 'junit:junit:+' + testImplementation libs.junit4 } diff --git a/build.gradle b/build.gradle index 1fcb28081..7a5b2861b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,9 +6,9 @@ buildscript { maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:7.4.1' - classpath 'com.google.gms:google-services:4.3.13' - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' + classpath libs.android.gradlePlugin + classpath libs.gms.googleServices + classpath libs.kotlin.gradlePlugin } } diff --git a/engine/build.gradle b/engine/build.gradle index 93facfd52..a64cced29 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -1,12 +1,13 @@ -apply plugin: 'com.android.library' +plugins { + id 'com.android.library' +} android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + compileSdk libs.versions.compileSdk.get().toInteger() defaultConfig { - minSdkVersion 19 - targetSdkVersion 30 + minSdk libs.versions.minSdk.get().toInteger() + targetSdk libs.versions.targetSdk.get().toInteger() } compileOptions { @@ -32,8 +33,8 @@ android { dependencies { // For the stable and dev app flavours we're using the library // build published at Maven Central. - stableImplementation 'org.ooni:oonimkall:2023.07.18-162729' - devImplementation 'org.ooni:oonimkall:2023.07.18-162729' + stableImplementation libs.ooni.oonimkall + devImplementation libs.ooni.oonimkall // For the experimental flavour, you need to compile your own // oonimkall.aar and put it into the ../engine-experimental dir diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..d26301e16 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,116 @@ +[versions] +androidGradlePlugin = "7.4.1" +barista = "3.9.0" +countlySdk = "21.11.0" +faker = "1.2.8" +mockitoCore = "5.3.1" +mockitoInline = "4.6.1" +robolectric = "4.6.1" +fastlaneScreengrab = "2.0.0" +sentryAndroid = "6.3.0" +xanscaleLocalhostToolkit = "19.05.01" +commonsIo = "2.6" +jacoco = "0.8.5" +kotlin = "1.6.21" + +# Android X +androidxCore = "1.5.0" +androidxRunner = "1.5.2" +androidxAppCompat = "1.6.1" +androidxConstraintlayout = "2.1.4" +androidxLifecycleProcess = "2.5.1" +androidxPreference = "1.2.0" +androidxLocalbroadcastmanager = "1.1.0" +androidxLegacySupportV4 = "1.0.0" +androidxJunit = "1.1.5" +androidxEspressoCore = "3.5.1" + +# Google +googleGson = "2.8.9" +googleGuava = "30.1.1-android" +googleMaterial = "1.6.1" +googleDagger = "2.36" +googleFirebaseBon = "26.3.0" +googlePlaycore = "1.10.3" + +# OONI +compileSdk = "34" +lottie = "3.0.7" +markwon = "2.0.1" +shapeofview = "1.3.2" +targetSdk = "34" +minSdk = "21" +oonimkall = "2023.07.18-162729" + +junit = "4.13.2" +dbflow = "4.2.4" +retrofitCore = "2.9.0" +retrofitLoggingInterceptor = "4.9.1" +butterknifeCore = "10.2.3" + +# Firebase Services +# https://firebase.google.com/support/release-notes/android +gms-googleServices = "4.3.15" + +[libraries] +# Dependencies of the included build-logic +android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } +barista = { module = "com.schibsted.spain:barista", version.ref = "barista" } +countly-sdk = { module = "ly.count.android:sdk", version.ref = "countlySdk" } +faker = { module = "com.github.blocoio:faker", version.ref = "faker" } +robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } +fastlane-screengrab = { module = "tools.fastlane:screengrab", version.ref = "fastlaneScreengrab" } +sentry-android = { module = "io.sentry:sentry-android", version.ref = "sentryAndroid" } +xanscale-localhost-toolkit = { module = "com.github.xanscale.LocalhostToolkit:app", version.ref = "xanscaleLocalhostToolkit" } +commons-io = { module = "commons-io:commons-io", version.ref = "commonsIo" } +kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } + +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" } +mockito-inline = { module = "org.mockito:mockito-inline", version.ref = "mockitoInline" } + +lottie = { module = "com.airbnb.android:lottie", version.ref = "lottie" } +markwon = { module = "ru.noties:markwon", version.ref = "markwon" } +retrofit-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofitCore" } +retrofit-logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "retrofitLoggingInterceptor" } +retrofit-lib = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitCore" } + +dbflow-lib = { module = "com.github.Raizlabs.DBFlow:dbflow", version.ref = "dbflow" } +dbflow-core = { module = "com.github.Raizlabs.DBFlow:dbflow-core", version.ref = "dbflow" } +dbflow-processor = { module = "com.github.Raizlabs.DBFlow:dbflow-processor", version.ref = "dbflow" } + +androidx-core = { module = "androidx.test:core", version.ref = "androidxCore" } +androidx-rules = { module = "androidx.test:rules", version.ref = "androidxCore" } +androidx-runner = { module = "androidx.test:runner", version.ref = "androidxRunner" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompat" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidxConstraintlayout" } +androidx-legacy-support-v4 = { module = "androidx.legacy:legacy-support-v4", version.ref = "androidxLegacySupportV4" } +androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "androidxLifecycleProcess" } +androidx-localbroadcastmanager = { module = "androidx.localbroadcastmanager:localbroadcastmanager", version.ref = "androidxLocalbroadcastmanager" } +androidx-preference = { module = "androidx.preference:preference", version.ref = "androidxPreference" } +androidx-junit = { module = "androidx.test.ext:junit", version.ref = "androidxJunit" } +androidx-espresso-contrib = { module = "androidx.test.espresso:espresso-contrib", version.ref = "androidxEspressoCore" } +androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidxEspressoCore" } +androidx-espresso-intents = { module = "androidx.test.espresso:espresso-intents", version.ref = "androidxEspressoCore" } + +google-play-core = { module = "com.google.android.play:core", version.ref = "googlePlaycore" } +google-gson = { module = "com.google.code.gson:gson", version.ref = "googleGson" } +google-guava = { module = "com.google.guava:guava", version.ref = "googleGuava" } +google-material = { module = "com.google.android.material:material", version.ref = "googleMaterial" } +google-dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "googleDagger" } +google-dagger = { module = "com.google.dagger:dagger", version.ref = "googleDagger" } +google-firebase-messaging = { module = "com.google.firebase:firebase-messaging"} +google-firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "googleFirebaseBon" } + +junit4 = { module = "junit:junit", version.ref = "junit" } +gms-googleServices = { module = "com.google.gms:google-services", version.ref = "gms-googleServices" } +ooni-oonimkall = { module = "org.ooni:oonimkall", version.ref = "oonimkall" } +shapeofview = { module = "com.github.florent37:shapeofview", version.ref = "shapeofview" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } +android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } + +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } + +gms-googleServices = { id = "com.google.gms.google-services", version.ref = "gms-googleServices"} diff --git a/settings.gradle b/settings.gradle index 8a8583d06..ee1a417a5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,3 +2,4 @@ include ':app' include ':engine' include ':engine-experimental' include ':applogger' +include ':shared-test' diff --git a/shared-test/.gitignore b/shared-test/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/shared-test/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/shared-test/build.gradle b/shared-test/build.gradle new file mode 100644 index 000000000..607a28dff --- /dev/null +++ b/shared-test/build.gradle @@ -0,0 +1,67 @@ +plugins { + id 'com.android.library' +} + +android { + namespace 'org.openobservatory.ooniprobe.shared.test' + compileSdk 33 + + defaultConfig { + minSdk 21 + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + flavorDimensions = ['testing', 'license'] + productFlavors { + stable { + dimension 'testing' + } + experimental { + dimension 'testing' + } + dev { + dimension 'testing' + } + + fdroid { + dimension 'license' + } + full { + dimension 'license' + } + } +} + +dependencies { + implementation project(":engine") + implementation project(":app") + + // Dependency Injection (https://dagger.dev/) + implementation libs.google.dagger + annotationProcessor libs.google.dagger.compiler + + // Database Library (https://github.com/agrosner/DBFlow) + implementation libs.dbflow.core + implementation libs.dbflow.lib + annotationProcessor libs.dbflow.processor + + // Gson Serialization Library (https://github.com/google/gson) + implementation libs.google.gson + + implementation libs.faker + implementation libs.commons.io + + // Networking Library (https://square.github.io/retrofit/) + implementation libs.retrofit.lib + implementation libs.retrofit.converter.gson + implementation libs.retrofit.logging.interceptor + + implementation libs.androidx.appcompat + + testImplementation libs.junit4 + androidTestImplementation libs.androidx.junit + androidTestImplementation libs.androidx.espresso.core +} diff --git a/shared-test/src/main/AndroidManifest.xml b/shared-test/src/main/AndroidManifest.xml new file mode 100644 index 000000000..a5918e68a --- /dev/null +++ b/shared-test/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/di/TestAppComponent.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/di/TestAppComponent.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/di/TestAppComponent.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/di/TestAppComponent.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/di/TestAppModule.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/di/TestAppModule.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/di/TestAppModule.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/di/TestAppModule.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/di/TestApplication.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/di/TestApplication.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/di/TestApplication.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/di/TestApplication.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/EventResultFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/EventResultFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/EventResultFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/EventResultFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/JsonResultFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/JsonResultFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/JsonResultFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/JsonResultFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/MeasurementFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/MeasurementFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/MeasurementFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/MeasurementFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/NetworkFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/NetworkFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/NetworkFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/NetworkFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/ResponseFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/ResponseFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/ResponseFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/ResponseFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/ResultFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/ResultFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/ResultFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/ResultFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/TestKeyFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/TestKeyFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/TestKeyFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/TestKeyFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/UrlFactory.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/factory/UrlFactory.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/factory/UrlFactory.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/factory/UrlFactory.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/DatabaseUtils.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/utils/DatabaseUtils.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/DatabaseUtils.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/utils/DatabaseUtils.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/FormattingUtils.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/utils/FormattingUtils.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/FormattingUtils.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/utils/FormattingUtils.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/TestSuiteUtils.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/utils/TestSuiteUtils.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/TestSuiteUtils.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/utils/TestSuiteUtils.java diff --git a/app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/models/TestSuiteMeasurements.java b/shared-test/src/main/java/org/openobservatory/ooniprobe/utils/models/TestSuiteMeasurements.java similarity index 100% rename from app/src/sharedTest/java/org/openobservatory/ooniprobe/utils/models/TestSuiteMeasurements.java rename to shared-test/src/main/java/org/openobservatory/ooniprobe/utils/models/TestSuiteMeasurements.java