Add print job settings screen.

Added a list of active print jobs to the main print settings
screen. Selecting a print job from there leads to a print job
settings screen with more information about the print job and
actions to change the prit job state such as cancel and restart.

bug:10935736

Change-Id: Idd6826a998309941c3d8478dafe4b039c8ca4f45
This commit is contained in:
Svetoslav Ganov
2013-09-23 15:48:23 -07:00
committed by Svetoslav
parent 077f83a22c
commit bc2c3db8f9
13 changed files with 793 additions and 74 deletions

View File

@@ -16,10 +16,14 @@
package com.android.settings.print;
import android.app.ActivityManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.AsyncTaskLoader;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
@@ -28,14 +32,23 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.print.PrintJob;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrintManager.PrintJobStateChangeListener;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import android.widget.TextView;
@@ -44,6 +57,8 @@ import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
/**
@@ -53,17 +68,24 @@ public class PrintSettingsFragment extends SettingsPreferenceFragment implements
static final char ENABLED_PRINT_SERVICES_SEPARATOR = ':';
private static final int LOADER_ID_PRINT_JOBS_LOADER = 1;
private static final String PRINT_JOBS_CATEGORY = "print_jobs_category";
private static final String PRINT_SERVICES_CATEGORY = "print_services_category";
// Extras passed to sub-fragments.
static final String EXTRA_PREFERENCE_KEY = "preference_key";
static final String EXTRA_CHECKED = "checked";
static final String EXTRA_TITLE = "title";
static final String EXTRA_ENABLE_WARNING_TITLE = "enable_warning_title";
static final String EXTRA_ENABLE_WARNING_MESSAGE = "enable_warning_message";
static final String EXTRA_SETTINGS_TITLE = "settings_title";
static final String EXTRA_SETTINGS_COMPONENT_NAME = "settings_component_name";
static final String EXTRA_ADD_PRINTERS_TITLE = "add_printers_title";
static final String EXTRA_ADD_PRINTERS_COMPONENT_NAME = "add_printers_component_name";
static final String EXTRA_SERVICE_COMPONENT_NAME = "service_component_name";
static final String EXTRA_PREFERENCE_KEY = "EXTRA_PREFERENCE_KEY";
static final String EXTRA_CHECKED = "EXTRA_CHECKED";
static final String EXTRA_TITLE = "EXTRA_TITLE";
static final String EXTRA_ENABLE_WARNING_TITLE = "EXTRA_ENABLE_WARNING_TITLE";
static final String EXTRA_ENABLE_WARNING_MESSAGE = "EXTRA_ENABLE_WARNING_MESSAGE";
static final String EXTRA_SETTINGS_TITLE = "EXTRA_SETTINGS_TITLE";
static final String EXTRA_SETTINGS_COMPONENT_NAME = "EXTRA_SETTINGS_COMPONENT_NAME";
static final String EXTRA_ADD_PRINTERS_TITLE = "EXTRA_ADD_PRINTERS_TITLE";
static final String EXTRA_ADD_PRINTERS_COMPONENT_NAME = "EXTRA_ADD_PRINTERS_COMPONENT_NAME";
static final String EXTRA_SERVICE_COMPONENT_NAME = "EXTRA_SERVICE_COMPONENT_NAME";
static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID";
private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
"EXTRA_PRINT_SERVICE_COMPONENT_NAME";
@@ -85,13 +107,27 @@ public class PrintSettingsFragment extends SettingsPreferenceFragment implements
}
};
private Preference mNoServicesMessagePreference;
private PreferenceCategory mActivePrintJobsCategory;
private PreferenceCategory mPrintServicesCategory;
private PrintJobsController mPrintJobsController;
private String mPrintJobPreferenceToActivate;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.print_settings);
getActivity().getActionBar().setTitle(R.string.print_settings_title);
mActivePrintJobsCategory = (PreferenceCategory) findPreference(
PRINT_JOBS_CATEGORY);
mPrintServicesCategory= (PreferenceCategory) findPreference(
PRINT_SERVICES_CATEGORY);
getPreferenceScreen().removePreference(mActivePrintJobsCategory);
mPrintJobsController = new PrintJobsController();
getActivity().getLoaderManager().initLoader(LOADER_ID_PRINT_JOBS_LOADER,
null, mPrintJobsController);
}
@Override
@@ -100,8 +136,8 @@ public class PrintSettingsFragment extends SettingsPreferenceFragment implements
mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
mSettingsContentObserver.register(getContentResolver());
updateServicesPreferences();
startPrintServiceSettingsIfNeeded();
setHasOptionsMenu(true);
startSubSettingsIfNeeded();
}
@Override
@@ -120,10 +156,26 @@ public class PrintSettingsFragment extends SettingsPreferenceFragment implements
Uri.parse(getString(R.string.download_print_service_query))));
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewGroup contentRoot = (ViewGroup) getListView().getParent();
View emptyView = getActivity().getLayoutInflater().inflate(
R.layout.empty_print_state, contentRoot, false);
TextView textView = (TextView) emptyView.findViewById(R.id.message);
textView.setText(R.string.print_no_services_installed);
contentRoot.addView(emptyView);
getListView().setEmptyView(emptyView);
}
private void updateServicesPreferences() {
// Since services category is auto generated we have to do a pass
// to generate it since services can come and go.
getPreferenceScreen().removeAll();
if (getPreferenceScreen().findPreference(PRINT_SERVICES_CATEGORY) == null) {
getPreferenceScreen().addPreference(mPrintServicesCategory);
} else {
// Since services category is auto generated we have to do a pass
// to generate it since services can come and go.
mPrintServicesCategory.removeAll();
}
List<ComponentName> enabledServices = SettingsUtils
.readEnabledPrintServices(getActivity());
@@ -194,30 +246,15 @@ public class PrintSettingsFragment extends SettingsPreferenceFragment implements
extras.putString(EXTRA_SERVICE_COMPONENT_NAME, componentName.flattenToString());
getPreferenceScreen().addPreference(preference);
mPrintServicesCategory.addPreference(preference);
}
if (getPreferenceScreen().getPreferenceCount() == 0) {
if (mNoServicesMessagePreference == null) {
mNoServicesMessagePreference = new Preference(getActivity()) {
@Override
protected void onBindView(View view) {
super.onBindView(view);
TextView summaryView = (TextView) view.findViewById(R.id.summary);
String title = getString(R.string.print_no_services_installed);
summaryView.setText(title);
}
};
mNoServicesMessagePreference.setPersistent(false);
mNoServicesMessagePreference.setLayoutResource(
R.layout.text_description_preference);
mNoServicesMessagePreference.setSelectable(false);
}
getPreferenceScreen().addPreference(mNoServicesMessagePreference);
if (mPrintServicesCategory.getPreferenceCount() == 0) {
getPreferenceScreen().removePreference(mPrintServicesCategory);
}
}
private void startPrintServiceSettingsIfNeeded() {
private void startSubSettingsIfNeeded() {
if (getArguments() == null) {
return;
}
@@ -228,6 +265,19 @@ public class PrintSettingsFragment extends SettingsPreferenceFragment implements
if (prereference != null) {
prereference.performClick(getPreferenceScreen());
}
} else {
String printJobId = getArguments().getString(EXTRA_PRINT_JOB_ID);
if (printJobId != null) {
getArguments().remove(EXTRA_PRINT_JOB_ID);
Preference preference = findPreference(printJobId);
if (preference != null) {
preference.performClick(getPreferenceScreen());
} else {
// The preference not being present may mean the the print job
// loader has not completed so make a note and wait for the load.
mPrintJobPreferenceToActivate = printJobId;
}
}
}
}
@@ -301,4 +351,207 @@ public class PrintSettingsFragment extends SettingsPreferenceFragment implements
@Override
public abstract void onChange(boolean selfChange, Uri uri);
}
private final class PrintJobsController implements LoaderCallbacks<List<PrintJobInfo>> {
@Override
public Loader<List<PrintJobInfo>> onCreateLoader(int id, Bundle args) {
if (id == LOADER_ID_PRINT_JOBS_LOADER) {
return new PrintJobsLoader(getActivity());
}
return null;
}
@Override
public void onLoadFinished(Loader<List<PrintJobInfo>> loader,
List<PrintJobInfo> printJobs) {
if (printJobs == null || printJobs.isEmpty()) {
getPreferenceScreen().removePreference(mActivePrintJobsCategory);
} else {
if (getPreferenceScreen().findPreference(PRINT_JOBS_CATEGORY) == null) {
getPreferenceScreen().addPreference(mActivePrintJobsCategory);
}
mActivePrintJobsCategory.removeAll();
final int printJobCount = printJobs.size();
for (int i = 0; i < printJobCount; i++) {
PrintJobInfo printJob = printJobs.get(i);
PreferenceScreen preference = getPreferenceManager()
.createPreferenceScreen(getActivity());
preference.setPersistent(false);
preference.setFragment(PrintJobSettingsFragment.class.getName());
preference.setKey(printJob.getId().flattenToString());
switch (printJob.getState()) {
case PrintJobInfo.STATE_QUEUED:
case PrintJobInfo.STATE_STARTED: {
preference.setTitle(getString(
R.string.print_printing_state_title_template,
printJob.getLabel()));
} break;
case PrintJobInfo.STATE_FAILED: {
preference.setTitle(getString(
R.string.print_failed_state_title_template,
printJob.getLabel()));
} break;
case PrintJobInfo.STATE_BLOCKED: {
preference.setTitle(getString(
R.string.print_blocked_state_title_template,
printJob.getLabel()));
} break;
}
preference.setSummary(getString(R.string.print_job_summary,
printJob.getPrinterName(), DateUtils.formatSameDayTime(
printJob.getCreationTime(), printJob.getCreationTime(),
DateFormat.SHORT, DateFormat.SHORT)));
switch (printJob.getState()) {
case PrintJobInfo.STATE_QUEUED:
case PrintJobInfo.STATE_STARTED: {
preference.setIcon(com.android.internal.R.drawable.ic_print);
} break;
case PrintJobInfo.STATE_FAILED:
case PrintJobInfo.STATE_BLOCKED: {
preference.setIcon(com.android.internal.R.drawable.ic_print_error);
} break;
}
Bundle extras = preference.getExtras();
extras.putParcelable(EXTRA_PRINT_JOB_ID, printJob.getId());
mActivePrintJobsCategory.addPreference(preference);
}
// If were waiting for creating a preference for a print
// job so we can start it - do that.
if (mPrintJobPreferenceToActivate != null) {
Preference preference = findPreference(mPrintJobPreferenceToActivate);
mPrintJobPreferenceToActivate = null;
if (preference != null) {
preference.performClick(getPreferenceScreen());
}
}
}
}
@Override
public void onLoaderReset(Loader<List<PrintJobInfo>> loader) {
getPreferenceScreen().removePreference(mActivePrintJobsCategory);
}
}
private static final class PrintJobsLoader extends AsyncTaskLoader<List<PrintJobInfo>> {
private static final String LOG_TAG = "PrintJobsLoader";
private static final boolean DEBUG = true;
private List <PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
private final PrintManager mPrintManager;
private PrintJobStateChangeListener mPrintJobStateChangeListener;
public PrintJobsLoader(Context context) {
super(context);
mPrintManager = ((PrintManager) context.getSystemService(
Context.PRINT_SERVICE)).getGlobalPrintManagerForUser(
ActivityManager.getCurrentUser());
}
@Override
public void deliverResult(List<PrintJobInfo> printJobs) {
if (isStarted()) {
super.deliverResult(printJobs);
}
}
@Override
protected void onStartLoading() {
if (DEBUG) {
Log.i(LOG_TAG, "onStartLoading()");
}
// If we already have a result, deliver it immediately.
if (!mPrintJobs.isEmpty()) {
deliverResult(new ArrayList<PrintJobInfo>(mPrintJobs));
}
// Start watching for changes.
if (mPrintJobStateChangeListener == null) {
mPrintJobStateChangeListener = new PrintJobStateChangeListener() {
@Override
public void onPrintJobsStateChanged(PrintJobId printJobId) {
onForceLoad();
}
};
mPrintManager.addPrintJobStateChangeListener(
mPrintJobStateChangeListener);
}
// If the data changed or we have no data - load it now.
if (mPrintJobs.isEmpty()) {
onForceLoad();
}
}
@Override
protected void onStopLoading() {
if (DEBUG) {
Log.i(LOG_TAG, "onStopLoading()");
}
// Cancel the load in progress if possible.
onCancelLoad();
}
@Override
protected void onReset() {
if (DEBUG) {
Log.i(LOG_TAG, "onReset()");
}
// Stop loading.
onStopLoading();
// Clear the cached result.
mPrintJobs.clear();
// Stop watching for changes.
if (mPrintJobStateChangeListener != null) {
mPrintManager.removePrintJobStateChangeListener(
mPrintJobStateChangeListener);
mPrintJobStateChangeListener = null;
}
}
@Override
public List<PrintJobInfo> loadInBackground() {
List<PrintJobInfo> printJobInfos = null;
List<PrintJob> printJobs = mPrintManager.getPrintJobs();
final int printJobCount = printJobs.size();
for (int i = 0; i < printJobCount; i++) {
PrintJobInfo printJob = printJobs.get(i).getInfo();
if (shouldShowToUser(printJob)) {
if (printJobInfos == null) {
printJobInfos = new ArrayList<PrintJobInfo>();
}
printJobInfos.add(printJob);
}
}
return printJobInfos;
}
private static boolean shouldShowToUser(PrintJobInfo printJob) {
switch (printJob.getState()) {
case PrintJobInfo.STATE_QUEUED:
case PrintJobInfo.STATE_STARTED:
case PrintJobInfo.STATE_BLOCKED:
case PrintJobInfo.STATE_FAILED: {
return true;
}
}
return false;
}
}
}