diff --git a/app/src/main/java/net/typeblog/shelter/ui/MainActivity.java b/app/src/main/java/net/typeblog/shelter/ui/MainActivity.java index e1f7e34..ccfd8e5 100644 --- a/app/src/main/java/net/typeblog/shelter/ui/MainActivity.java +++ b/app/src/main/java/net/typeblog/shelter/ui/MainActivity.java @@ -15,6 +15,7 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; +import androidx.activity.result.ActivityResult; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; @@ -112,7 +113,12 @@ public class MainActivity extends AppCompatActivity { .setNegativeButton(R.string.first_run_alert_cancel, (dialog, which) -> finish()) .show();*/ - startActivity(new Intent(this, SetupWizardActivity.class)); + registerForActivityResult(new SetupWizardActivity.SetupWizardContract(), (Boolean result) -> { + if (result) + init(); + else + finish(); + }).launch(null); } else { // Initialize the settings SettingsManager.getInstance().applyAll(); diff --git a/app/src/main/java/net/typeblog/shelter/ui/SetupWizardActivity.java b/app/src/main/java/net/typeblog/shelter/ui/SetupWizardActivity.java index 2913ccf..9dd84d9 100644 --- a/app/src/main/java/net/typeblog/shelter/ui/SetupWizardActivity.java +++ b/app/src/main/java/net/typeblog/shelter/ui/SetupWizardActivity.java @@ -1,12 +1,15 @@ package net.typeblog.shelter.ui; +import androidx.activity.result.contract.ActivityResultContract; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; +import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -19,10 +22,13 @@ import com.android.setupwizardlib.view.NavigationBar; import net.typeblog.shelter.R; public class SetupWizardActivity extends AppCompatActivity { + private DevicePolicyManager mPolicyManager = null; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_setup_wizard); + mPolicyManager = getSystemService(DevicePolicyManager.class); // Don't use switchToFragment for the first time // because we don't want animation for the first fragment // (it would have nothing to animate upon, resulting in a black background) @@ -43,6 +49,30 @@ public class SetupWizardActivity extends AppCompatActivity { .commit(); } + private void finishWithResult(boolean succeeded) { + setResult(succeeded ? RESULT_OK : RESULT_CANCELED); + finish(); + } + + private void setupProfile() { + // Placeholder + switchToFragment(new FailedFragment(), false); + } + + public static class SetupWizardContract extends ActivityResultContract { + @NonNull + @Override + public Intent createIntent(@NonNull Context context, Void input) { + return new Intent(context, SetupWizardActivity.class); + } + + @Override + public Boolean parseResult(int resultCode, @Nullable Intent intent) { + return resultCode == RESULT_OK; + } + } + + // ==== SetupWizard steps ==== private static abstract class BaseWizardFragment extends Fragment implements NavigationBar.NavigationBarListener { protected SetupWizardActivity mActivity = null; protected SetupWizardLayout mWizard = null; @@ -195,10 +225,69 @@ public class SetupWizardActivity extends AppCompatActivity { mActivity.switchToFragment(new CompatibilityFragment(), true); } + @Override + public void onNavigateNext() { + super.onNavigateNext(); + mActivity.switchToFragment(new PleaseWaitFragment(), false); + } + @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mWizard.setHeaderText(R.string.setup_wizard_ready); } } + + public static class PleaseWaitFragment extends TextWizardFragment { + @Override + protected int getLayoutResource() { + return R.layout.fragment_setup_wizard_generic_text; + } + + @Override + protected int getTextRes() { + return R.string.setup_wizard_please_wait_text; + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + mActivity.setupProfile(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mWizard.setHeaderText(R.string.setup_wizard_please_wait); + mWizard.setProgressBarColor(view.getContext().getColorStateList(R.color.setup_wizard_progress_bar)); + mWizard.setProgressBarShown(true); + mWizard.getNavigationBar().getBackButton().setVisibility(View.GONE); + mWizard.getNavigationBar().getNextButton().setVisibility(View.GONE); + } + } + + public static class FailedFragment extends TextWizardFragment { + @Override + protected int getLayoutResource() { + return R.layout.fragment_setup_wizard_generic_text; + } + + @Override + protected int getTextRes() { + return R.string.setup_wizard_failed_text; + } + + @Override + public void onNavigateNext() { + super.onNavigateNext(); + mActivity.finishWithResult(false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mWizard.setHeaderText(R.string.setup_wizard_failed); + mWizard.getNavigationBar().getBackButton().setVisibility(View.GONE); + } + } } \ No newline at end of file diff --git a/app/src/main/res/color/setup_wizard_progress_bar.xml b/app/src/main/res/color/setup_wizard_progress_bar.xml new file mode 100644 index 0000000..db5ff16 --- /dev/null +++ b/app/src/main/res/color/setup_wizard_progress_bar.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index deb24d5..a61264d 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -3,6 +3,7 @@ #FAFAFA #C2C2C2 #009688 + #FFC107 #333333 #999999 #E0F2F1 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 68b81d1..3bfe436 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -17,6 +17,10 @@ Shelter is developed and tested on AOSP-like Android derivatives. This includes AOSP (Android Open Source Project), Google Android (on Pixels), and most AOSP-based open-source custom ROMs such as LineageOS. If your phone is running one of the Android derivatives listed above, then congratulations! Shelter is probably going to work correctly on your device.\n\nSome device vendors introduce very invasive customizations into the Android code base, resulting in conflicts, incompatibility and unexpected behavior. Some custom ROMs can also introduce compatibility-breaking changes, but generally these are rarer occurrences compared to phone vendor-introduced incompatibilities.\n\nSheler is merely an interface into the Work Profile feature provided by the system. If the feature provided by the system is broken or non-standard, Shelter could not magically resolve the issue on its own. If you are currently using a vendor-modified Android version that is known to break Work Profiles, you have been warned. You may proceed anyway, but there is no guarantee that Shelter would behave correctly under these circumstances. Ready? We are now ready to set up Shelter for you. Please first ensure that your device is not in Do Not Disturb mode, because you will need to click on a notification later to finalize the setup process.\n\nWhen you are ready, click on \"Next\" to begin the setup process. + Please wait… + We are trying to initialize Work Profile and set up Shelter on your device. + Setup failed + We regret to inform you that we were not able to set up Shelter for you.\n\nIf you did not cancel the setup manually, then the reason for the failure is most commonly due to a heavily modified system, or a conflict between Shelter and other Work Profile managers. Unfortunately, there is not much that we could do about this.\n\nClick "Next" to exit. Shelter Important