SettingsFragment: add option to enable CrossProfileDocumentProvider

This commit is contained in:
Peter Cai 2018-09-19 14:19:00 +08:00
parent 202f9ff964
commit ae0e82712d
No known key found for this signature in database
GPG key ID: 71F5FB4E4F3FD54F
10 changed files with 128 additions and 2 deletions

View file

@ -54,6 +54,7 @@
<!-- When the intent is actually already forwarded to work profile -->
<action android:name="net.typeblog.shelter.action.START_FILE_SHUTTLE" />
<action android:name="net.typeblog.shelter.action.START_FILE_SHUTTLE_2" />
<action android:name="net.typeblog.shelter.action.SYNCHRONIZE_PREFERENCE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@ -89,7 +90,8 @@
android:authorities="net.typeblog.shelter.documents"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS"
android:exported="true">
android:exported="true"
android:enabled="false">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>

View file

@ -8,6 +8,7 @@ import android.content.ServiceConnection;
import net.typeblog.shelter.services.FileShuttleService;
import net.typeblog.shelter.services.ShelterService;
import net.typeblog.shelter.util.LocalStorageManager;
import net.typeblog.shelter.util.SettingsManager;
public class ShelterApplication extends Application {
private ServiceConnection mShelterServiceConnection = null;
@ -17,6 +18,7 @@ public class ShelterApplication extends Application {
public void onCreate() {
super.onCreate();
LocalStorageManager.initialize(this);
SettingsManager.initialize(this);
}
public void bindShelterService(ServiceConnection conn, boolean foreground) {

View file

@ -26,6 +26,7 @@ import net.typeblog.shelter.services.IFileShuttleService;
import net.typeblog.shelter.services.IFileShuttleServiceCallback;
import net.typeblog.shelter.util.FileProviderProxy;
import net.typeblog.shelter.util.LocalStorageManager;
import net.typeblog.shelter.util.SettingsManager;
import net.typeblog.shelter.util.Utility;
import java.io.File;
@ -51,6 +52,7 @@ public class DummyActivity extends Activity {
// This is a bad experience, so we use two to avoid this.
public static final String START_FILE_SHUTTLE = "net.typeblog.shelter.action.START_FILE_SHUTTLE";
public static final String START_FILE_SHUTTLE_2 = "net.typeblog.shelter.action.START_FILE_SHUTTLE_2";
public static final String SYNCHRONIZE_PREFERENCE = "net.typeblog.shelter.action.SYNCHRONIZE_PREFERENCE";
private static final int REQUEST_INSTALL_PACKAGE = 1;
private static final int REQUEST_PERMISSION_EXTERNAL_STORAGE= 2;
@ -69,6 +71,7 @@ public class DummyActivity extends Activity {
// so that we can make sure those are updated with our app
Utility.enforceWorkProfilePolicies(this);
Utility.enforceUserRestrictions(this);
SettingsManager.getInstance().applyAll();
}
Intent intent = getIntent();
@ -93,6 +96,8 @@ public class DummyActivity extends Activity {
actionFreezeAllInList();
} else if (START_FILE_SHUTTLE.equals(intent.getAction()) || START_FILE_SHUTTLE_2.equals(intent.getAction())) {
actionStartFileShuttle();
} else if (SYNCHRONIZE_PREFERENCE.equals(intent.getAction())) {
actionSynchronizePreference();
} else {
finish();
}
@ -331,4 +336,15 @@ public class DummyActivity extends Activity {
}
});
}
private void actionSynchronizePreference() {
String name = getIntent().getStringExtra("name");
if (getIntent().hasExtra("boolean")) {
LocalStorageManager.getInstance()
.setBoolean(name, getIntent().getBooleanExtra("boolean", false));
}
// TODO: Cases for other types
SettingsManager.getInstance().applyAll();
finish();
}
}

View file

@ -31,6 +31,7 @@ import net.typeblog.shelter.services.IAppInstallCallback;
import net.typeblog.shelter.services.IShelterService;
import net.typeblog.shelter.services.KillerService;
import net.typeblog.shelter.util.LocalStorageManager;
import net.typeblog.shelter.util.SettingsManager;
import net.typeblog.shelter.util.UriForwardProxy;
import net.typeblog.shelter.util.Utility;
@ -120,6 +121,8 @@ public class MainActivity extends AppCompatActivity {
(dialog, which) -> finish())
.show();
} else {
// Initialize the settings
SettingsManager.getInstance().applyAll();
// Initialize the app (start by binding the services)
bindServices();
}

View file

@ -4,15 +4,22 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import net.typeblog.shelter.R;
import net.typeblog.shelter.util.SettingsManager;
public class SettingsFragment extends PreferenceFragmentCompat {
public class SettingsFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener {
private static final String SETTINGS_VERSION = "settings_version";
private static final String SETTINGS_SOURCE_CODE = "settings_source_code";
private static final String SETTINGS_BUG_REPORT = "settings_bug_report";
private static final String SETTINGS_CROSS_PROFILE_FILE_CHOOSER = "settings_cross_profile_file_chooser";
private SettingsManager mManager = SettingsManager.getInstance();
private CheckBoxPreference mPrefCrossProfileFileChooser = null;
@Override
public void onCreatePreferences(Bundle bundle, String s) {
@ -32,6 +39,11 @@ public class SettingsFragment extends PreferenceFragmentCompat {
.setOnPreferenceClickListener(this::openSummaryUrl);
findPreference(SETTINGS_BUG_REPORT)
.setOnPreferenceClickListener(this::openSummaryUrl);
// === Interactions ===
mPrefCrossProfileFileChooser = (CheckBoxPreference) findPreference(SETTINGS_CROSS_PROFILE_FILE_CHOOSER);
mPrefCrossProfileFileChooser.setChecked(mManager.getCrossProfileFileChooserEnabled());
mPrefCrossProfileFileChooser.setOnPreferenceChangeListener(this);
}
private boolean openSummaryUrl(Preference pref) {
@ -40,4 +52,14 @@ public class SettingsFragment extends PreferenceFragmentCompat {
startActivity(intent);
return true;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newState) {
if (preference == mPrefCrossProfileFileChooser) {
mManager.setCrossProfileFileChooserEnabled((boolean) newState);
return true;
} else {
return false;
}
}
}

View file

@ -12,6 +12,7 @@ public class LocalStorageManager {
public static final String PREF_IS_SETTING_UP = "is_setting_up";
public static final String PREF_HAS_SETUP = "has_setup";
public static final String PREF_AUTO_FREEZE_LIST_WORK_PROFILE = "auto_freeze_list_work_profile";
public static final String PREF_CROSS_PROFILE_FILE_CHOOSER = "cross_profile_file_chooser";
private static final String LIST_DIVIDER = ",";

View file

@ -0,0 +1,62 @@
package net.typeblog.shelter.util;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import net.typeblog.shelter.ui.DummyActivity;
public class SettingsManager {
private static SettingsManager sInstance = null;
public static void initialize(Context context) {
sInstance = new SettingsManager(context);
}
public static SettingsManager getInstance() {
return sInstance;
}
private LocalStorageManager mStorage = LocalStorageManager.getInstance();
private Context mContext;
private SettingsManager(Context context) {
mContext = context;
}
private void syncSettingsToProfileBool(String name, boolean value) {
Intent intent = new Intent(DummyActivity.SYNCHRONIZE_PREFERENCE);
intent.putExtra("name", name);
intent.putExtra("boolean", value);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Utility.transferIntentToProfile(mContext, intent);
mContext.startActivity(intent);
}
// Enforce all settings
public void applyAll() {
applyCrossProfileFileChooser();
}
// Read and apply the enabled state of the cross profile file chooser
public void applyCrossProfileFileChooser() {
boolean enabled = mStorage.getBoolean(LocalStorageManager.PREF_CROSS_PROFILE_FILE_CHOOSER);
mContext.getPackageManager().setComponentEnabledSetting(
new ComponentName(mContext, CrossProfileDocumentsProvider.class),
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
// Set the enabled state of the cross profile file chooser
public void setCrossProfileFileChooserEnabled(boolean enabled) {
mStorage.setBoolean(LocalStorageManager.PREF_CROSS_PROFILE_FILE_CHOOSER, enabled);
applyCrossProfileFileChooser();
syncSettingsToProfileBool(LocalStorageManager.PREF_CROSS_PROFILE_FILE_CHOOSER, enabled);
}
// Get the enabled state of the cross profile file chooser
public boolean getCrossProfileFileChooserEnabled() {
return mStorage.getBoolean(LocalStorageManager.PREF_CROSS_PROFILE_FILE_CHOOSER);
}
}

View file

@ -116,6 +116,11 @@ public class Utility {
new IntentFilter(DummyActivity.START_FILE_SHUTTLE_2),
DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
manager.addCrossProfileIntentFilter(
adminComponent,
new IntentFilter(DummyActivity.SYNCHRONIZE_PREFERENCE),
DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
// Allow ACTION_SEND and ACTION_SEND_MULTIPLE to cross from managed to parent
// TODO: Make this configurable
IntentFilter actionSendFilter = new IntentFilter();

View file

@ -36,6 +36,9 @@
<!-- Settings Options -->
<string name="settings">Settings</string>
<string name="settings_interaction">Interaction</string>
<string name="settings_cross_profile_file_chooser">Cross-profile Documents UI</string>
<string name="settings_cross_profile_file_chooser_desc">When enabled, an option will be shown in the system\'s Documents UI (named Files or Downloads on your launcher) and apps that support Documents UI to allow browsing / viewing / picking / copying files in Shelter from main profile and vice-versa.</string>
<string name="settings_about">About</string>
<string name="settings_version">Version</string>
<string name="settings_source_code">Source Code</string>

View file

@ -2,6 +2,16 @@
<android.support.v7.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.preference.PreferenceCategory
android:title="@string/settings_interaction">
<android.support.v7.preference.CheckBoxPreference
android:key="settings_cross_profile_file_chooser"
android:title="@string/settings_cross_profile_file_chooser"
android:summary="@string/settings_cross_profile_file_chooser_desc" />
</android.support.v7.preference.PreferenceCategory>
<android.support.v7.preference.PreferenceCategory
android:title="@string/settings_about">