Add an upsell dialog to activate the storage manager.

After a manual clear, the user will be prompted to turn
on the storage manager, if it is turned off. The prompt
will only show up after certain defined delay times and
stop showing up entirely if denied enough times.

Currently, the dialog does not actually turn on the storage
manager because the storage manager is not yet landed.

Bug: 28801159

Change-Id: I3c221786d08a7102b3b5357416ab12692d1894cf
This commit is contained in:
Daniel Nishi
2016-05-16 12:19:58 -07:00
parent 1ca6867e35
commit 0216e9dc2e
4 changed files with 162 additions and 1 deletions

View File

@@ -7611,4 +7611,13 @@
<!-- Dropdown preference title for dropdown describing how many days of data to retain.--> <!-- Dropdown preference title for dropdown describing how many days of data to retain.-->
<string name="automatic_storage_manager_days_title">Remove photos &amp; videos</string> <string name="automatic_storage_manager_days_title">Remove photos &amp; videos</string>
<!-- Title for the dialog to up sell the storage manager. [CHAR LIMIT=NONE] -->
<string name="deletion_helper_upsell_title"><xliff:g id="used" example="1.2GB">%1$s</xliff:g> now free. Manage storage automatically?</string>
<!-- Summary for the dialog to up sell the storage manager. [CHAR LIMIT=NONE] -->
<string name="deletion_helper_upsell_summary">Let Storage manager automatically free up space by removing backed up content from your device?</string>
<!-- Button to delay turning on the storage manager on the storage manager upsell. [CHAR LIMIT=20]-->
<string name="deletion_helper_upsell_cancel">No thanks</string>
<!-- Button to activate the storage manager on the storage manager upsell. [CHAR LIMIT=20]-->
<string name="deletion_helper_upsell_activate">Turn on</string>
</resources> </resources>

View File

@@ -17,6 +17,7 @@
package com.android.settings.deletionhelper; package com.android.settings.deletionhelper;
import android.app.Application; import android.app.Application;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceGroup;
@@ -48,6 +49,9 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
ApplicationsState.Callbacks, AppStateBaseBridge.Callback, ApplicationsState.Callbacks, AppStateBaseBridge.Callback,
Preference.OnPreferenceChangeListener, DeletionType.FreeableChangedListener, Preference.OnPreferenceChangeListener, DeletionType.FreeableChangedListener,
View.OnClickListener { View.OnClickListener {
public static final int CLEAR_DATA_RESULT = 1;
public static final String FREED_BYTES_KEY = "freed";
private static final String TAG = "DeletionHelperFragment"; private static final String TAG = "DeletionHelperFragment";
private static final String EXTRA_HAS_BRIDGE = "hasBridge"; private static final String EXTRA_HAS_BRIDGE = "hasBridge";
@@ -332,6 +336,10 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
Log.e(TAG, "An error occurred while uninstalling packages."); Log.e(TAG, "An error occurred while uninstalling packages.");
} }
}); });
Intent data = new Intent();
data.putExtra(FREED_BYTES_KEY, getTotalFreeableSpace());
getActivity().setResult(CLEAR_DATA_RESULT, data);
task.run(); task.run();
finishFragment(); finishFragment();
} }

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.deletionhelper;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.format.Formatter;
import com.android.settings.R;
import android.util.Log;
import java.util.concurrent.TimeUnit;
/**
* Fragment for activating the storage manager after a manual clear.
*/
public class StorageManagerUpsellDialog extends DialogFragment
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
public static final String TAG = "StorageManagerUpsellDialog";
private static final String SHARED_PREFERENCES_NAME = "StorageManagerUpsellDialog";
private static final String NEXT_SHOW_TIME = "next_show_time";
private static final String DISMISSED_COUNT = "dismissed_count";
private static final String NO_THANKS_COUNT = "no_thanks_count";
private static final String ARGS_FREED_BYTES = "freed_bytes";
private static final long NEVER = -1;
private static final long DISMISS_SHORT_DELAY = TimeUnit.DAYS.toMillis(14);
private static final long DISMISS_LONG_DELAY = TimeUnit.DAYS.toMillis(90);
private static final int DISMISS_LONG_THRESHOLD = 9;
private static final long NO_THANKS_SHORT_DELAY = TimeUnit.DAYS.toMillis(90);
private static final long NO_THANKS_LONG_DELAY = NEVER;
private static final int NO_THANKS_LONG_THRESHOLD = 3;
public static StorageManagerUpsellDialog newInstance(long freedBytes) {
StorageManagerUpsellDialog dialog = new StorageManagerUpsellDialog();
Bundle args = new Bundle(1);
args.putLong(ARGS_FREED_BYTES, freedBytes);
dialog.setArguments(args);
return dialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle args = getArguments();
long freedBytes = args.getLong(ARGS_FREED_BYTES);
final Context context = getContext();
return new AlertDialog.Builder(context)
.setTitle(context.getString(R.string.deletion_helper_upsell_title,
Formatter.formatFileSize(context, freedBytes)))
.setMessage(context.getString(R.string.deletion_helper_upsell_summary))
.setPositiveButton(R.string.deletion_helper_upsell_activate, this)
.setNegativeButton(R.string.deletion_helper_upsell_cancel, this)
.create();
}
@Override
public void onClick(DialogInterface dialog, int buttonId) {
if (buttonId == DialogInterface.BUTTON_POSITIVE) {
// TODO: Activate the storage manager once the storage manager is landed.
} else {
SharedPreferences sp = getSharedPreferences(getContext());
int noThanksCount = sp.getInt(NO_THANKS_COUNT, 0) + 1;
SharedPreferences.Editor editor = sp.edit();
editor.putInt(NO_THANKS_COUNT, noThanksCount);
editor.putLong(NEXT_SHOW_TIME,
System.currentTimeMillis() + getNoThanksDelay(noThanksCount));
editor.apply();
}
}
@Override
public void onCancel(DialogInterface dialog) {
SharedPreferences sp = getSharedPreferences(getContext());
int dismissCount = sp.getInt(DISMISSED_COUNT, 0) + 1;
SharedPreferences.Editor editor = sp.edit();
editor.putInt(DISMISSED_COUNT, dismissCount);
editor.putLong(NEXT_SHOW_TIME,
System.currentTimeMillis() + getDismissDelay(dismissCount));
editor.apply();
}
/**
* Returns if the dialog should be shown, given the delays between when it is shown.
* @param context Context to get shared preferences for determining the next show time.
*/
public static boolean shouldShow(Context context) {
// TODO: If the Storage Manager is enabled, return false.
long nextTimeToShow = getSharedPreferences(context).getLong(NEXT_SHOW_TIME, 0);
if (nextTimeToShow == NEVER) {
return false;
}
return System.currentTimeMillis() > nextTimeToShow;
}
private static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
}
private static long getNoThanksDelay(int noThanksCount) {
return (noThanksCount > NO_THANKS_LONG_THRESHOLD)
? NO_THANKS_LONG_DELAY : NO_THANKS_SHORT_DELAY;
}
private static long getDismissDelay(int dismissCount) {
return (dismissCount > DISMISS_LONG_THRESHOLD)
? DISMISS_LONG_DELAY : DISMISS_SHORT_DELAY;
}
}

View File

@@ -60,6 +60,7 @@ import com.android.settings.Utils;
import com.android.settings.applications.ManageApplications; import com.android.settings.applications.ManageApplications;
import com.android.settings.deletionhelper.DeletionHelperFragment; import com.android.settings.deletionhelper.DeletionHelperFragment;
import com.android.settings.deletionhelper.AutomaticStorageManagerSettings; import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
import com.android.settings.deletionhelper.StorageManagerUpsellDialog;
import com.android.settings.deviceinfo.StorageSettings.MountTask; import com.android.settings.deviceinfo.StorageSettings.MountTask;
import com.android.settingslib.deviceinfo.StorageMeasurement; import com.android.settingslib.deviceinfo.StorageMeasurement;
import com.android.settingslib.deviceinfo.StorageMeasurement.MeasurementDetails; import com.android.settingslib.deviceinfo.StorageMeasurement.MeasurementDetails;
@@ -100,6 +101,9 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment {
R.string.storage_detail_other R.string.storage_detail_other
}; };
private static final int DELETION_HELPER_SETTINGS = 1;
private static final int DELETION_HELPER_CLEAR = 1;
private StorageManager mStorageManager; private StorageManager mStorageManager;
private UserManager mUserManager; private UserManager mUserManager;
@@ -418,7 +422,7 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment {
return true; return true;
case R.id.storage_free: case R.id.storage_free:
startFragment(this, DeletionHelperFragment.class.getCanonicalName(), startFragment(this, DeletionHelperFragment.class.getCanonicalName(),
R.string.deletion_helper_title, 0, args); R.string.deletion_helper_title, DELETION_HELPER_SETTINGS, args);
return true; return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
@@ -507,6 +511,18 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment {
return super.onPreferenceTreeClick(pref); return super.onPreferenceTreeClick(pref);
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == DELETION_HELPER_SETTINGS && resultCode == DELETION_HELPER_CLEAR &&
StorageManagerUpsellDialog.shouldShow(getActivity())) {
long freedBytes = data.getLongExtra(DeletionHelperFragment.FREED_BYTES_KEY, 0);
StorageManagerUpsellDialog dialog =
StorageManagerUpsellDialog.newInstance(freedBytes);
dialog.show(getFragmentManager(), StorageManagerUpsellDialog.TAG);
}
}
private final MeasurementReceiver mReceiver = new MeasurementReceiver() { private final MeasurementReceiver mReceiver = new MeasurementReceiver() {
@Override @Override
public void onDetailsChanged(MeasurementDetails details) { public void onDetailsChanged(MeasurementDetails details) {