From 6e1bed82d7ff44c2bd165fb2ff934c75df277626 Mon Sep 17 00:00:00 2001 From: Norbel Ambanumben Date: Tue, 22 Aug 2023 17:17:45 +0100 Subject: [PATCH 1/5] Update censorship measurement prompt to show in new activity --- app/src/main/AndroidManifest.xml | 5 + .../ooniprobe/activity/MainActivity.java | 78 +------- .../ooniprobe/activity/PromptActivity.java | 171 ++++++++++++++++++ .../ooniprobe/di/ActivityComponent.java | 2 + app/src/main/res/drawable/ooni_phone.xml | 141 +++++++++++++++ app/src/main/res/layout/activity_prompt.xml | 85 +++++++++ 6 files changed, 410 insertions(+), 72 deletions(-) create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/activity/PromptActivity.java create mode 100644 app/src/main/res/drawable/ooni_phone.xml create mode 100644 app/src/main/res/layout/activity_prompt.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 78c0d0b76..52a00b6af 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -172,6 +172,11 @@ + + requestPermissionLauncher; - public static Intent newIntent(Context context, int resItem) { return new Intent(context, MainActivity.class).putExtra(RES_ITEM, resItem).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); } @@ -101,14 +87,11 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { .withExtra(AUTOTEST_DIALOG) .build().show(getSupportFragmentManager(), null); } else if (notificationManager.shouldShow()) { - new ConfirmDialogFragment.Builder() - .withTitle(getString(R.string.Modal_EnableNotifications_Title)) - .withMessage(getString(R.string.Modal_EnableNotifications_Paragraph)) - .withPositiveButton(getString(R.string.Modal_SoundsGreat)) - .withNegativeButton(getString(R.string.Modal_NotNow)) - .withNeutralButton(getString(R.string.Modal_DontAskAgain)) - .withExtra(NOTIFICATION_DIALOG) - .build().show(getSupportFragmentManager(), null); + registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { + if (result.getResultCode() == Activity.RESULT_OK) { + // TODO (aanorbel) Notify Users of successful completion + } + }).launch(PromptActivity.newIntent(this, PromptActivity.Prompt.CENSORSHIP_CONSENT)); } ThirdPartyServices.checkUpdates(this); } @@ -122,46 +105,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); } } - requestNotificationPermission(); } - private void requestNotificationPermission() { - - requestPermissionLauncher = registerForActivityResult( - new ActivityResultContracts.RequestPermission(), - (result) -> { - if (!result) { - Snackbar.make( - binding.getRoot(), - "Please grant Notification permission from App Settings", - Snackbar.LENGTH_LONG - ).setAction(R.string.Settings_Title, view -> { - Intent intent = new Intent(); - intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS"); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - //for Android 5-7 - intent.putExtra("app_package", getPackageName()); - intent.putExtra("app_uid", getApplicationInfo().uid); - - // for Android 8 and above - intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName()); - - startActivity(intent); - }).show(); - } - } - ); - NotificationUtility.setChannel(getApplicationContext(), CHANNEL_ID, getString(R.string.Settings_AutomatedTesting_Label), false, false, false); - if (ContextCompat.checkSelfPermission( - this, - Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED - ) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS); - } - } - } @Override protected void onNewIntent(Intent intent) { @@ -183,17 +128,6 @@ else if (intent.getExtras().containsKey(NOTIFICATION_DIALOG)){ @Override public void onConfirmation(Serializable extra, int i) { if (extra == null) return; - if (extra.equals(NOTIFICATION_DIALOG)) { - notificationManager.getUpdates(i == DialogInterface.BUTTON_POSITIVE); - - //If positive answer reload consents and init notification - if (i == DialogInterface.BUTTON_POSITIVE){ - ThirdPartyServices.reloadConsents((Application) getApplication()); - } - else if (i == DialogInterface.BUTTON_NEUTRAL){ - notificationManager.disableAskNotificationDialog(); - } - } if (extra.equals(AUTOTEST_DIALOG)) { preferenceManager.setNotificationsFromDialog(i == DialogInterface.BUTTON_POSITIVE); if (i == DialogInterface.BUTTON_POSITIVE){ diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/PromptActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/PromptActivity.java new file mode 100644 index 000000000..1d3945e49 --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/PromptActivity.java @@ -0,0 +1,171 @@ +package org.openobservatory.ooniprobe.activity; + + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.view.View; + +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.StringRes; +import androidx.core.content.ContextCompat; + +import com.google.android.material.snackbar.Snackbar; + +import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.databinding.ActivityPromptBinding; +import org.openobservatory.ooniprobe.domain.UpdatesNotificationManager; + +import javax.inject.Inject; + +public class PromptActivity extends AbstractActivity { + private static final String PROMPT_ITEM = "promptItem"; + @Inject + UpdatesNotificationManager notificationManager; + private ActivityPromptBinding binding; + private Prompt prompt; + + private ActivityResultLauncher requestPermissionLauncher; + + public static Intent newIntent(Context context, Prompt prompt) { + return new Intent(context, PromptActivity.class).putExtra(PROMPT_ITEM, prompt); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getActivityComponent().inject(this); + binding = ActivityPromptBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + prompt = (Prompt) getIntent().getExtras().get(PROMPT_ITEM); + binding.title.setText(prompt.title); + binding.description.setText(prompt.paragraph); + + registerPermissionRequest(); + setUpClickListeners(); + } + + private void registerPermissionRequest() { + requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), (result) -> { + if (!result) { + Snackbar.make(binding.getRoot(), "Please grant Notification permission from App Settings", Snackbar.LENGTH_LONG).setAction(R.string.Settings_Title, view -> { + Intent intent = new Intent(); + intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + //for Android 5-7 + intent.putExtra("app_package", getPackageName()); + intent.putExtra("app_uid", getApplicationInfo().uid); + + // for Android 8 and above + intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName()); + + startActivity(intent); + }).show(); + } + setResult(result ? Activity.RESULT_OK : Activity.RESULT_CANCELED); + finish(); + }); + } + + private void setUpClickListeners() { + OnPromptAction actions; + switch (prompt) { + case CENSORSHIP_CONSENT: + actions = new ConsentActions(); + break; + case TEST_PROGRESS_CONSENT: + actions = new ConsentActions(); + break; + default: + actions = new OnPromptAction() { + @Override + public void onClickPositive(View view) { + } + + @Override + public void onClickNeutral(View view) { + } + + @Override + public void onClickNegative(View view) { + } + }; + } + + binding.soundsGreat.setOnClickListener(actions::onClickPositive); + binding.notNow.setOnClickListener(actions::onClickNeutral); + binding.dontAskAgain.setOnClickListener(actions::onClickNegative); + } + + public void requestNotificationPermission() { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS); + } + } + } + + enum Prompt { + CENSORSHIP_CONSENT(R.string.Modal_EnableNotifications_Title, R.string.Modal_EnableNotifications_Paragraph), TEST_PROGRESS_CONSENT(R.string.Modal_EnableNotifications_Title, R.string.Modal_EnableNotifications_Paragraph); + + private final int title; + private final int paragraph; + + Prompt(@StringRes int title, @StringRes int paragraph) { + this.title = title; + this.paragraph = paragraph; + } + } + + interface OnPromptAction { + /** + * Callback for View#onClick of `soundsGreat` button. + * + * @param view + */ + void onClickPositive(View view); + + /** + * Callback for View#onClick of `notNow` button. + * + * @param view + */ + void onClickNeutral(View view); + + /** + * Callback for View#onClick of `dontAskAgain` button. + * + * @param view + */ + void onClickNegative(View view); + } + + public class ConsentActions implements OnPromptAction { + + @Override + public void onClickPositive(View view) { + notificationManager.getUpdates(true); + PromptActivity.this.requestNotificationPermission(); + } + + @Override + public void onClickNeutral(View view) { + PromptActivity.this.setResult(Activity.RESULT_CANCELED); + PromptActivity.this.finish(); + } + + @Override + public void onClickNegative(View view) { + notificationManager.disableAskNotificationDialog(); + onClickNeutral(view); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java b/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java index f88835ebf..e3a54992b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java @@ -7,6 +7,7 @@ import org.openobservatory.ooniprobe.activity.MeasurementDetailActivity; import org.openobservatory.ooniprobe.activity.OoniRunActivity; import org.openobservatory.ooniprobe.activity.OverviewActivity; +import org.openobservatory.ooniprobe.activity.PromptActivity; import org.openobservatory.ooniprobe.activity.ProxyActivity; import org.openobservatory.ooniprobe.activity.ResultDetailActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; @@ -28,4 +29,5 @@ public interface ActivityComponent { void inject(RunningActivity activity); void inject(TextActivity activity); void inject(LogActivity activity); + void inject(PromptActivity activity); } \ No newline at end of file diff --git a/app/src/main/res/drawable/ooni_phone.xml b/app/src/main/res/drawable/ooni_phone.xml new file mode 100644 index 000000000..231083216 --- /dev/null +++ b/app/src/main/res/drawable/ooni_phone.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_prompt.xml b/app/src/main/res/layout/activity_prompt.xml new file mode 100644 index 000000000..8699537b1 --- /dev/null +++ b/app/src/main/res/layout/activity_prompt.xml @@ -0,0 +1,85 @@ + + + + + + + + + +