summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/print/PrintServiceSettingsFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings/print/PrintServiceSettingsFragment.java')
-rw-r--r--src/com/android/settings/print/PrintServiceSettingsFragment.java519
1 files changed, 519 insertions, 0 deletions
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
new file mode 100644
index 0000000..c65e43e
--- /dev/null
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2013 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.print;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.LoaderManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.Loader;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceActivity;
+import android.print.PrintManager;
+import android.print.PrinterDiscoverySession;
+import android.print.PrinterDiscoverySession.OnPrintersChangeListener;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.print.PrintSettingsFragment.ToggleSwitch;
+import com.android.settings.print.PrintSettingsFragment.ToggleSwitch.OnBeforeCheckedChangeListener;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Fragment with print service settings.
+ */
+public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
+ implements DialogInterface.OnClickListener {
+
+ private static final int LOADER_ID_PRINTERS_LOADER = 1;
+
+ private static final int DIALOG_ID_ENABLE_WARNING = 1;
+
+ private final SettingsContentObserver mSettingsContentObserver =
+ new SettingsContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ List<ComponentName> services = SettingsUtils.readEnabledPrintServices(getActivity());
+ final boolean enabled = services.contains(mComponentName);
+ mToggleSwitch.setCheckedInternal(enabled);
+ }
+ };
+
+ protected ToggleSwitch mToggleSwitch;
+
+ protected String mPreferenceKey;
+
+ protected CharSequence mSettingsTitle;
+ protected Intent mSettingsIntent;
+
+ protected CharSequence mAddPrintersTitle;
+ protected Intent mAddPrintersIntent;
+
+ private CharSequence mEnableWarningTitle;
+ private CharSequence mEnableWarningMessage;
+
+ private ComponentName mComponentName;
+
+ // TODO: Showing sub-sub fragment does not handle the activity title
+ // so we do it but this is wrong. Do a real fix when there is time.
+ private CharSequence mOldActivityTitle;
+
+ @Override
+ public void onResume() {
+ mSettingsContentObserver.register(getContentResolver());
+ super.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ mSettingsContentObserver.unregister(getContentResolver());
+ super.onPause();
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ onInstallActionBarToggleSwitch();
+ processArguments(getArguments());
+ getListView().setAdapter(new PrintersAdapter());
+ }
+
+ @Override
+ public void onDestroyView() {
+ getActivity().getActionBar().setCustomView(null);
+ if (mOldActivityTitle != null) {
+ getActivity().getActionBar().setTitle(mOldActivityTitle);
+ }
+ mToggleSwitch.setOnBeforeCheckedChangeListener(null);
+ super.onDestroyView();
+ }
+
+ private void onPreferenceToggled(String preferenceKey, boolean enabled) {
+ ComponentName service = ComponentName.unflattenFromString(preferenceKey);
+ List<ComponentName> services = SettingsUtils.readEnabledPrintServices(getActivity());
+ if (enabled) {
+ services.add(service);
+ } else {
+ services.remove(service);
+ }
+ SettingsUtils.writeEnabledPrintServices(getActivity(), services);
+ }
+
+ @Override
+ public Dialog onCreateDialog(int dialogId) {
+ CharSequence title = null;
+ CharSequence message = null;
+ switch (dialogId) {
+ case DIALOG_ID_ENABLE_WARNING:
+ title = mEnableWarningTitle;
+ message = mEnableWarningMessage;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(title)
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setMessage(message)
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .create();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final boolean checked;
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ checked = true;
+ mToggleSwitch.setCheckedInternal(checked);
+ getArguments().putBoolean(PrintSettingsFragment.EXTRA_CHECKED, checked);
+ onPreferenceToggled(mPreferenceKey, checked);
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ checked = false;
+ mToggleSwitch.setCheckedInternal(checked);
+ getArguments().putBoolean(PrintSettingsFragment.EXTRA_CHECKED, checked);
+ onPreferenceToggled(mPreferenceKey, checked);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ protected void onInstallActionBarToggleSwitch() {
+ mToggleSwitch = createAndAddActionBarToggleSwitch(getActivity());
+ mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
+ @Override
+ public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
+ if (checked) {
+ if (!TextUtils.isEmpty(mEnableWarningMessage)) {
+ toggleSwitch.setCheckedInternal(false);
+ getArguments().putBoolean(PrintSettingsFragment.EXTRA_CHECKED, false);
+ showDialog(DIALOG_ID_ENABLE_WARNING);
+ return true;
+ }
+ onPreferenceToggled(mPreferenceKey, true);
+ } else {
+ onPreferenceToggled(mPreferenceKey, false);
+ }
+ return false;
+ }
+ });
+ }
+
+ private void processArguments(Bundle arguments) {
+ // Key.
+ mPreferenceKey = arguments.getString(PrintSettingsFragment.EXTRA_PREFERENCE_KEY);
+
+ // Enabled.
+ final boolean enabled = arguments.getBoolean(PrintSettingsFragment.EXTRA_CHECKED);
+ mToggleSwitch.setCheckedInternal(enabled);
+
+ // Title.
+ PreferenceActivity activity = (PreferenceActivity) getActivity();
+ if (!activity.onIsMultiPane() || activity.onIsHidingHeaders()) {
+ mOldActivityTitle = getActivity().getTitle();
+ String title = arguments.getString(PrintSettingsFragment.EXTRA_TITLE);
+ getActivity().getActionBar().setTitle(title);
+ }
+
+ // Settings title and intent.
+ String settingsTitle = arguments.getString(PrintSettingsFragment.EXTRA_SETTINGS_TITLE);
+ String settingsComponentName = arguments.getString(
+ PrintSettingsFragment.EXTRA_SETTINGS_COMPONENT_NAME);
+ if (!TextUtils.isEmpty(settingsTitle) && !TextUtils.isEmpty(settingsComponentName)) {
+ Intent settingsIntent = new Intent(Intent.ACTION_MAIN).setComponent(
+ ComponentName.unflattenFromString(settingsComponentName.toString()));
+ if (!getPackageManager().queryIntentActivities(settingsIntent, 0).isEmpty()) {
+ mSettingsTitle = settingsTitle;
+ mSettingsIntent = settingsIntent;
+ setHasOptionsMenu(true);
+ }
+ }
+
+ // Add printers title and intent.
+ String addPrintersTitle = arguments.getString(
+ PrintSettingsFragment.EXTRA_ADD_PRINTERS_TITLE);
+ String addPrintersComponentName =
+ arguments.getString(PrintSettingsFragment.EXTRA_ADD_PRINTERS_COMPONENT_NAME);
+ if (!TextUtils.isEmpty(addPrintersTitle)
+ && !TextUtils.isEmpty(addPrintersComponentName)) {
+ Intent addPritnersIntent = new Intent(Intent.ACTION_MAIN).setComponent(
+ ComponentName.unflattenFromString(addPrintersComponentName.toString()));
+ if (!getPackageManager().queryIntentActivities(addPritnersIntent, 0).isEmpty()) {
+ mAddPrintersTitle = addPrintersTitle;
+ mAddPrintersIntent = addPritnersIntent;
+ setHasOptionsMenu(true);
+ }
+ }
+
+ // Enable warning title.
+ mEnableWarningTitle = arguments.getCharSequence(
+ PrintSettingsFragment.EXTRA_ENABLE_WARNING_TITLE);
+
+ // Enable warning message.
+ mEnableWarningMessage = arguments.getCharSequence(
+ PrintSettingsFragment.EXTRA_ENABLE_WARNING_MESSAGE);
+
+ // Component name.
+ mComponentName = ComponentName.unflattenFromString(arguments
+ .getString(PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME));
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.print_service_settings, menu);
+
+ MenuItem addPrinters = menu.findItem(R.id.print_menu_item_add_printer);
+ if (!TextUtils.isEmpty(mAddPrintersTitle) && mAddPrintersIntent != null) {
+ addPrinters.setIntent(mAddPrintersIntent);
+ } else {
+ menu.removeItem(R.id.print_menu_item_add_printer);
+ }
+
+ MenuItem settings = menu.findItem(R.id.print_menu_item_settings);
+ if (!TextUtils.isEmpty(mSettingsTitle) && mSettingsIntent != null) {
+ settings.setIntent(mSettingsIntent);
+ } else {
+ menu.removeItem(R.id.print_menu_item_settings);
+ }
+
+ MenuItem uninstall = menu.findItem(R.id.print_menu_item_uninstall);
+ Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE,
+ Uri.parse("package:" + mComponentName.getPackageName()));
+ uninstall.setIntent(uninstallIntent);
+ }
+
+ private ToggleSwitch createAndAddActionBarToggleSwitch(Activity activity) {
+ ToggleSwitch toggleSwitch = new ToggleSwitch(activity);
+ final int padding = activity.getResources().getDimensionPixelSize(
+ R.dimen.action_bar_switch_padding);
+ toggleSwitch.setPaddingRelative(0, 0, padding, 0);
+ activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+ ActionBar.DISPLAY_SHOW_CUSTOM);
+ activity.getActionBar().setCustomView(toggleSwitch,
+ new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,
+ ActionBar.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_VERTICAL | Gravity.END));
+ return toggleSwitch;
+ }
+
+ private static abstract class SettingsContentObserver extends ContentObserver {
+
+ public SettingsContentObserver(Handler handler) {
+ super(handler);
+ }
+
+ public void register(ContentResolver contentResolver) {
+ contentResolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.ENABLED_PRINT_SERVICES), false, this);
+ }
+
+ public void unregister(ContentResolver contentResolver) {
+ contentResolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public abstract void onChange(boolean selfChange, Uri uri);
+
+ }
+
+ private final class PrintersAdapter extends BaseAdapter
+ implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>{
+ private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
+
+ public PrintersAdapter() {
+ getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
+ }
+
+ @Override
+ public int getCount() {
+ return mPrinters.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mPrinters.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = getActivity().getLayoutInflater().inflate(
+ R.layout.preference, parent, false);
+ }
+
+ PrinterInfo printer = (PrinterInfo) getItem(position);
+ CharSequence title = printer.getName();
+ CharSequence subtitle = null;
+ try {
+ PackageInfo packageInfo = getPackageManager().getPackageInfo(
+ printer.getId().getServiceName().getPackageName(), 0);
+ subtitle = packageInfo.applicationInfo.loadLabel(getPackageManager());
+ } catch (NameNotFoundException nnfe) {
+ /* ignore */
+ }
+
+ TextView titleView = (TextView) convertView.findViewById(android.R.id.title);
+ titleView.setText(title);
+
+ TextView subtitleView = (TextView) convertView.findViewById(android.R.id.summary);
+ if (!TextUtils.isEmpty(subtitle)) {
+ subtitleView.setText(subtitle);
+ subtitleView.setVisibility(View.VISIBLE);
+ } else {
+ subtitleView.setText(null);
+ subtitleView.setVisibility(View.GONE);
+ }
+
+ return convertView;
+ }
+
+ @Override
+ public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
+ if (id == LOADER_ID_PRINTERS_LOADER) {
+ return new PrintersLoader(getActivity());
+ }
+ return null;
+ }
+
+ @Override
+ public void onLoadFinished(Loader<List<PrinterInfo>> loader,
+ List<PrinterInfo> printers) {
+ mPrinters.clear();
+ final int printerCount = printers.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo printer = printers.get(i);
+ if (printer.getId().getServiceName().equals(mComponentName)) {
+ mPrinters.add(printer);
+ }
+ }
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
+ mPrinters.clear();
+ notifyDataSetInvalidated();
+ }
+ }
+
+ private static class PrintersLoader extends Loader<List<PrinterInfo>> {
+
+ private static final String LOG_TAG = "PrintersLoader";
+
+ private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
+
+ private final Map<PrinterId, PrinterInfo> mPrinters =
+ new LinkedHashMap<PrinterId, PrinterInfo>();
+
+ private PrinterDiscoverySession mDiscoverySession;
+
+ public PrintersLoader(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void deliverResult(List<PrinterInfo> printers) {
+ if (isStarted()) {
+ super.deliverResult(printers);
+ }
+ }
+
+ @Override
+ protected void onStartLoading() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onStartLoading()");
+ }
+ // The contract is that if we already have a valid,
+ // result the we have to deliver it immediately.
+ if (!mPrinters.isEmpty()) {
+ deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+ }
+ // We want to start discovery at this point.
+ onForceLoad();
+ }
+
+ @Override
+ protected void onStopLoading() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onStopLoading()");
+ }
+ onCancelLoad();
+ }
+
+ @Override
+ protected void onForceLoad() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onForceLoad()");
+ }
+ loadInternal();
+ }
+
+ @Override
+ protected boolean onCancelLoad() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onCancelLoad()");
+ }
+ return cancelInternal();
+ }
+
+ @Override
+ protected void onReset() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onReset()");
+ }
+ onStopLoading();
+ mPrinters.clear();
+ if (mDiscoverySession != null) {
+ mDiscoverySession.destroy();
+ mDiscoverySession = null;
+ }
+ }
+
+ @Override
+ protected void onAbandon() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onAbandon()");
+ }
+ onStopLoading();
+ }
+
+ private boolean cancelInternal() {
+ if (mDiscoverySession != null
+ && mDiscoverySession.isPrinterDiscoveryStarted()) {
+ mDiscoverySession.stopPrinterDiscovery();
+ return true;
+ }
+ return false;
+ }
+
+ private void loadInternal() {
+ if (mDiscoverySession == null) {
+ PrintManager printManager = (PrintManager) getContext()
+ .getSystemService(Context.PRINT_SERVICE);
+ mDiscoverySession = printManager.createPrinterDiscoverySession();
+ mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener() {
+ @Override
+ public void onPrintersChanged() {
+ deliverResult(new ArrayList<PrinterInfo>(
+ mDiscoverySession.getPrinters()));
+ }
+ });
+ }
+ mDiscoverySession.startPrinterDisovery(null);
+ }
+ }
+}
+