From 530cee79de4f8fdfe9d00629cf687c7050cb70d3 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Thu, 18 Mar 2021 16:30:58 +0800 Subject: [PATCH] refactor: MainActivity: use the new result contract to choose APKs --- .../net/typeblog/shelter/ui/MainActivity.java | 55 ++++++++++--------- .../net/typeblog/shelter/util/Utility.java | 28 ++++++++++ 2 files changed, 58 insertions(+), 25 deletions(-) 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 6ef3f80..499d8ae 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.MenuItem; import android.widget.Toast; import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; @@ -45,12 +46,17 @@ public class MainActivity extends AppCompatActivity { private static final int REQUEST_START_SERVICE_IN_WORK_PROFILE = 2; private static final int REQUEST_TRY_START_SERVICE_IN_WORK_PROFILE = 4; - private static final int REQUEST_DOCUMENTS_CHOOSE_APK = 5; private final ActivityResultLauncher mStartSetup = registerForActivityResult(new SetupWizardActivity.SetupWizardContract(), this::setupWizardCb); private final ActivityResultLauncher mResumeSetup = registerForActivityResult(new SetupWizardActivity.ResumeSetupContract(), this::setupWizardCb); + private final ActivityResultLauncher mSelectApk = + registerForActivityResult( + new Utility.ActivityResultContractInputWrapper<>( + new ActivityResultContracts.OpenDocument(), + new String[]{"application/vnd.android.package-archive"}), + this::onApkSelected); private LocalStorageManager mStorage = null; @@ -364,10 +370,7 @@ public class MainActivity extends AppCompatActivity { "shelter-freeze-all", getString(R.string.freeze_all_shortcut)); return true; case R.id.main_menu_install_app_to_profile: - Intent openApkIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT); - openApkIntent.addCategory(Intent.CATEGORY_OPENABLE); - openApkIntent.setType("application/vnd.android.package-archive"); - startActivityForResult(openApkIntent, REQUEST_DOCUMENTS_CHOOSE_APK); + mSelectApk.launch(null); return true; case R.id.main_menu_show_all: Runnable update = () -> { @@ -397,6 +400,27 @@ public class MainActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } + private void onApkSelected(Uri uri) { + if (uri == null) return; + UriForwardProxy proxy = new UriForwardProxy(getApplicationContext(), uri); + + try { + mServiceWork.installApk(proxy, new IAppInstallCallback.Stub() { + @Override + public void callback(int result) { + runOnUiThread(() -> { + // The other side will have closed the Fd for us + if (result == RESULT_OK) + Toast.makeText(MainActivity.this, + R.string.install_app_to_profile_success, Toast.LENGTH_LONG).show(); + }); + } + }); + } catch (RemoteException e) { + // Well, I don't know what to do then + } + } + @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (requestCode == REQUEST_TRY_START_SERVICE_IN_WORK_PROFILE) { @@ -419,26 +443,7 @@ public class MainActivity extends AppCompatActivity { registerStartActivityProxies(); startKiller(); buildView(); - } else if (requestCode == REQUEST_DOCUMENTS_CHOOSE_APK && resultCode == RESULT_OK && data != null) { - Uri uri = data.getData(); - UriForwardProxy proxy = new UriForwardProxy(getApplicationContext(), uri); - - try { - mServiceWork.installApk(proxy, new IAppInstallCallback.Stub() { - @Override - public void callback(int result) { - runOnUiThread(() -> { - // The other side will have closed the Fd for us - if (result == RESULT_OK) - Toast.makeText(MainActivity.this, - R.string.install_app_to_profile_success, Toast.LENGTH_LONG).show(); - }); - } - }); - } catch (RemoteException e) { - // Well, I don't know what to do then - } - } else { + } else { super.onActivityResult(requestCode, resultCode, data); } } diff --git a/app/src/main/java/net/typeblog/shelter/util/Utility.java b/app/src/main/java/net/typeblog/shelter/util/Utility.java index 21e312d..f5f5686 100644 --- a/app/src/main/java/net/typeblog/shelter/util/Utility.java +++ b/app/src/main/java/net/typeblog/shelter/util/Utility.java @@ -29,6 +29,10 @@ import android.provider.MediaStore; import android.provider.Settings; import android.widget.Toast; +import androidx.activity.result.contract.ActivityResultContract; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import net.typeblog.shelter.R; import net.typeblog.shelter.receivers.ShelterDeviceAdminReceiver; import net.typeblog.shelter.services.IShelterService; @@ -501,4 +505,28 @@ public class Utility { .setSmallIcon(icon) .build(); } + + // A wrapper over arbitrary ActivityResultContract that provides + // hardcoded input parameters and do not accept input with launch() + public static class ActivityResultContractInputWrapper> + extends ActivityResultContract { + private final T mInner; + private final I mInput; + + public ActivityResultContractInputWrapper(T inner, I input) { + mInner = inner; + mInput = input; + } + + @NonNull + @Override + public Intent createIntent(@NonNull Context context, Void input) { + return mInner.createIntent(context, mInput); + } + + @Override + public O parseResult(int resultCode, @Nullable Intent intent) { + return mInner.parseResult(resultCode, intent); + } + } }