Merge "Implementing print settings as per UX spec." into klp-dev

This commit is contained in:
Svetoslav
2013-09-05 00:18:48 +00:00
committed by Android (Google) Code Review
14 changed files with 959 additions and 606 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/print_menu_item_add_printer"
android:title="@string/print_menu_item_add_printer"
android:showAsAction="ifRoom">
</item>
<item
android:id="@+id/print_menu_item_settings"
android:title="@string/print_menu_item_settings"
android:showAsAction="ifRoom">
</item>
<item
android:id="@+id/print_menu_item_uninstall"
android:title="@string/print_menu_item_uninstall"
android:showAsAction="never">
</item>
</menu>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/print_menu_item_download_print_service"
android:title="@string/print_menu_item_download_print_service"
android:showAsAction="ifRoom">
</item>
</menu>

View File

@@ -33,5 +33,7 @@
<item>@string/input_method_selector_always_show_value</item>
<item>@string/input_method_selector_always_hide_value</item>
</string-array>
<!-- Default query string to search for a print service. -->
<string name="download_print_service_query">market://search?q=print service</string>
</resources>

View File

@@ -3393,9 +3393,7 @@
<!-- Title in main settings screen for printing settings [CHAR LIMIT=15] -->
<string name="print_settings">Printing</string>
<!-- Title for print service settings screen [CHAR LIMIT=25] -->
<string name="print_settings_title">Printing settings</string>
<!-- Title for the printing preference category of print services. [CHAR LIMIT=25] -->
<string name="print_services_title">Services</string>
<string name="print_settings_title">Print services</string>
<!-- Title for a warning message about security implications of enabling a print service,
displayed as a dialog message when the user selects to enable a print service (tablet). [CHAR LIMIT=NONE] -->
@@ -3421,6 +3419,18 @@
<!-- Summary for the disabled state of a print feature. [CHAR LIMIT=10] -->
<string name="print_feature_state_off">Off</string>
<!-- Title of the action bar button to got to Play Store to download a print service. [CHAR LIMIT=25] -->
<string name="print_menu_item_download_print_service">I don\'t see mine</string>
<!-- Title of the action bar button to got to add a printer. [CHAR LIMIT=25] -->
<string name="print_menu_item_add_printer">Add printer</string>
<!-- Title of the action bar button uninstall a print service. [CHAR LIMIT=25] -->
<string name="print_menu_item_uninstall">Uninstall</string>
<!-- Title for the printer categoty showing a list of available printers. [CHAR LIMIT=25] -->
<string name="category_printers">Printers</string>
<!-- App Fuel Gauge strings -->
<skip />

View File

@@ -17,10 +17,4 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/print_settings_title">
<PreferenceCategory
android:key="services_category"
android:title="@string/print_services_title">
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -184,8 +184,8 @@
<!-- Print -->
<header
android:id="@+id/print_settings"
android:fragment="com.android.settings.PrintingSettings"
android:icon="@drawable/ic_settings_accessibility"
android:fragment="com.android.settings.print.PrintSettingsFragment"
android:icon="@drawable/ic_print"
android:title="@string/print_settings" />
<!-- Development -->

View File

@@ -1,587 +0,0 @@
/*
* 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;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Switch;
import android.widget.TextView;
import com.android.internal.content.PackageMonitor;
import com.android.settings.PrintingSettings.ToggleSwitch.OnBeforeCheckedChangeListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Activity with the printing settings.
*/
public class PrintingSettings extends SettingsPreferenceFragment implements DialogCreatable {
private static final char ENABLED_PRINT_SERVICES_SEPARATOR = ':';
// Preference categories
private static final String SERVICES_CATEGORY = "services_category";
// Extras passed to sub-fragments.
private static final String EXTRA_PREFERENCE_KEY = "preference_key";
private static final String EXTRA_CHECKED = "checked";
private static final String EXTRA_TITLE = "title";
private static final String EXTRA_ENABLE_WARNING_TITLE = "enable_warning_title";
private static final String EXTRA_ENABLE_WARNING_MESSAGE = "enable_warning_message";
private static final String EXTRA_SETTINGS_TITLE = "settings_title";
private static final String EXTRA_SETTINGS_COMPONENT_NAME = "settings_component_name";
private static final String EXTRA_ADD_PRINTERS_TITLE = "add_printers_title";
private static final String EXTRA_ADD_PRINTERS_COMPONENT_NAME = "add_printers_component_name";
private static final String EXTRA_SERVICE_COMPONENT_NAME = "service_component_name";
// Auxiliary members.
private final static SimpleStringSplitter sStringColonSplitter =
new SimpleStringSplitter(ENABLED_PRINT_SERVICES_SEPARATOR);
private static final List<ResolveInfo> sInstalledServicesList = new ArrayList<ResolveInfo>();
private static final Set<ComponentName> sEnabledServiceNameSet = new HashSet<ComponentName>();
private final PackageMonitor mSettingsPackageMonitor = new SettingsPackageMonitor();
private final Handler mHandler = new Handler() {
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
loadInstalledServices(getActivity());
loadEnabledServices(getActivity());
updateServicesPreferences();
}
};
private final SettingsContentObserver mSettingsContentObserver =
new SettingsContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
loadInstalledServices(getActivity());
loadEnabledServices(getActivity());
updateServicesPreferences();
}
};
// Preference controls.
private PreferenceCategory mServicesCategory;
private Preference mNoServicesMessagePreference;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.print_settings);
mServicesCategory = (PreferenceCategory) findPreference(SERVICES_CATEGORY);
}
@Override
public void onResume() {
super.onResume();
mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
mSettingsContentObserver.register(getContentResolver());
loadInstalledServices(getActivity());
loadEnabledServices(getActivity());
updateServicesPreferences();
}
@Override
public void onPause() {
mSettingsPackageMonitor.unregister();
mSettingsContentObserver.unregister(getContentResolver());
super.onPause();
}
private void updateServicesPreferences() {
// Since services category is auto generated we have to do a pass
// to generate it since services can come and go.
mServicesCategory.removeAll();
final int installedServiceCount = sInstalledServicesList.size();
for (int i = 0; i < installedServiceCount; i++) {
ResolveInfo installedService = sInstalledServicesList.get(i);
PreferenceScreen preference = getPreferenceManager().createPreferenceScreen(
getActivity());
String title = installedService.loadLabel(getPackageManager()).toString();
preference.setTitle(title);
ComponentName componentName = new ComponentName(
installedService.serviceInfo.packageName,
installedService.serviceInfo.name);
preference.setKey(componentName.flattenToString());
final boolean serviceEnabled = sEnabledServiceNameSet.contains(componentName);
if (serviceEnabled) {
preference.setSummary(getString(R.string.print_feature_state_on));
} else {
preference.setSummary(getString(R.string.print_feature_state_off));
}
preference.setOrder(i);
preference.setFragment(TogglePrintServicePreferenceFragment.class.getName());
preference.setPersistent(false);
Bundle extras = preference.getExtras();
extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey());
extras.putBoolean(EXTRA_CHECKED, serviceEnabled);
extras.putString(EXTRA_TITLE, title);
PrintServiceInfo printServiceInfo = PrintServiceInfo.create(
installedService, getActivity());
CharSequence applicationLabel = installedService.loadLabel(getPackageManager());
extras.putString(EXTRA_ENABLE_WARNING_TITLE, getString(
R.string.print_service_security_warning_title, applicationLabel));
extras.putString(EXTRA_ENABLE_WARNING_MESSAGE, getString(
R.string.print_service_security_warning_summary, applicationLabel));
String settingsClassName = printServiceInfo.getSettingsActivityName();
if (!TextUtils.isEmpty(settingsClassName)) {
extras.putString(EXTRA_SETTINGS_TITLE,
getString(R.string.print_menu_item_settings));
extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
new ComponentName(installedService.serviceInfo.packageName,
settingsClassName).flattenToString());
}
String addPrinterClassName = printServiceInfo.getAddPrintersActivityName();
if (!TextUtils.isEmpty(addPrinterClassName)) {
extras.putString(EXTRA_ADD_PRINTERS_TITLE,
getString(R.string.print_menu_item_add_printers));
extras.putString(EXTRA_ADD_PRINTERS_COMPONENT_NAME,
new ComponentName(installedService.serviceInfo.packageName,
addPrinterClassName).flattenToString());
}
extras.putString(EXTRA_SERVICE_COMPONENT_NAME, componentName.flattenToString());
mServicesCategory.addPreference(preference);
}
if (mServicesCategory.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);
}
mServicesCategory.addPreference(mNoServicesMessagePreference);
}
}
private static void loadInstalledServices(Context context) {
sInstalledServicesList.clear();
List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentServices(
new Intent(android.printservice.PrintService.SERVICE_INTERFACE),
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
final int resolveInfoCount = resolveInfos.size();
for (int i = 0, count = resolveInfoCount; i < count; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
sInstalledServicesList.add(resolveInfo);
}
}
private static void loadEnabledServices(Context context) {
sEnabledServiceNameSet.clear();
String enabledServicesSetting = Settings.Secure.getString(context
.getContentResolver(), Settings.Secure.ENABLED_PRINT_SERVICES);
if (enabledServicesSetting == null) {
enabledServicesSetting = "";
}
SimpleStringSplitter colonSplitter = sStringColonSplitter;
colonSplitter.setString(enabledServicesSetting);
while (colonSplitter.hasNext()) {
String componentNameString = colonSplitter.next();
ComponentName enabledService = ComponentName.unflattenFromString(
componentNameString);
sEnabledServiceNameSet.add(enabledService);
}
}
private class SettingsPackageMonitor extends PackageMonitor {
@Override
public void onPackageAdded(String packageName, int uid) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageAppeared(String packageName, int reason) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageDisappeared(String packageName, int reason) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageRemoved(String packageName, int uid) {
mHandler.obtainMessage().sendToTarget();
}
}
public static class ToggleSwitch extends Switch {
private OnBeforeCheckedChangeListener mOnBeforeListener;
public static interface OnBeforeCheckedChangeListener {
public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked);
}
public ToggleSwitch(Context context) {
super(context);
}
public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) {
mOnBeforeListener = listener;
}
@Override
public void setChecked(boolean checked) {
if (mOnBeforeListener != null
&& mOnBeforeListener.onBeforeCheckedChanged(this, checked)) {
return;
}
super.setChecked(checked);
}
public void setCheckedInternal(boolean checked) {
super.setChecked(checked);
}
}
public static class TogglePrintServicePreferenceFragment
extends ToggleFeaturePreferenceFragment implements DialogInterface.OnClickListener {
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) {
String settingValue = Settings.Secure.getString(getContentResolver(),
Settings.Secure.ENABLED_PRINT_SERVICES);
final boolean enabled = settingValue.contains(mComponentName);
mToggleSwitch.setCheckedInternal(enabled);
}
};
private CharSequence mEnableWarningTitle;
private CharSequence mEnableWarningMessage;
private String mComponentName;
@Override
public void onResume() {
mSettingsContentObserver.register(getContentResolver());
super.onResume();
}
@Override
public void onPause() {
mSettingsContentObserver.unregister(getContentResolver());
super.onPause();
}
@Override
public void onPreferenceToggled(String preferenceKey, boolean enabled) {
Set<ComponentName> enabledServices = sEnabledServiceNameSet;
ComponentName toggledService = ComponentName.unflattenFromString(preferenceKey);
if (enabled) {
enabledServices.add(toggledService);
} else {
enabledServices.remove(toggledService);
}
StringBuilder enabledServicesBuilder = new StringBuilder();
for (ComponentName enabledService : enabledServices) {
enabledServicesBuilder.append(enabledService.flattenToString());
enabledServicesBuilder.append(ENABLED_PRINT_SERVICES_SEPARATOR);
}
final int enabledServicesBuilderLength = enabledServicesBuilder.length();
if (enabledServicesBuilderLength > 0) {
enabledServicesBuilder.deleteCharAt(enabledServicesBuilderLength - 1);
}
Settings.Secure.putString(getContentResolver(),
Settings.Secure.ENABLED_PRINT_SERVICES,
enabledServicesBuilder.toString());
}
@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(EXTRA_CHECKED, checked);
onPreferenceToggled(mPreferenceKey, checked);
break;
case DialogInterface.BUTTON_NEGATIVE:
checked = false;
mToggleSwitch.setCheckedInternal(checked);
getArguments().putBoolean(EXTRA_CHECKED, checked);
onPreferenceToggled(mPreferenceKey, checked);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
protected void onInstallActionBarToggleSwitch() {
super.onInstallActionBarToggleSwitch();
mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
@Override
public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
if (checked) {
if (!TextUtils.isEmpty(mEnableWarningMessage)) {
toggleSwitch.setCheckedInternal(false);
getArguments().putBoolean(EXTRA_CHECKED, false);
showDialog(DIALOG_ID_ENABLE_WARNING);
return true;
}
onPreferenceToggled(mPreferenceKey, true);
} else {
onPreferenceToggled(mPreferenceKey, false);
}
return false;
}
});
}
@Override
protected void onProcessArguments(Bundle arguments) {
super.onProcessArguments(arguments);
// Settings title and intent.
String settingsTitle = arguments.getString(EXTRA_SETTINGS_TITLE);
String settingsComponentName = arguments.getString(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(EXTRA_ADD_PRINTERS_TITLE);
String addPrintersComponentName =
arguments.getString(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(
PrintingSettings.EXTRA_ENABLE_WARNING_TITLE);
// Enable warning message.
mEnableWarningMessage = arguments.getCharSequence(
PrintingSettings.EXTRA_ENABLE_WARNING_MESSAGE);
// Component name.
mComponentName = arguments.getString(EXTRA_SERVICE_COMPONENT_NAME);
}
}
public static abstract class ToggleFeaturePreferenceFragment
extends SettingsPreferenceFragment {
protected ToggleSwitch mToggleSwitch;
protected String mPreferenceKey;
protected CharSequence mSettingsTitle;
protected Intent mSettingsIntent;
protected CharSequence mAddPrintersTitle;
protected Intent mAddPrintersIntent;
// 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 onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
getActivity());
setPreferenceScreen(preferenceScreen);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
onInstallActionBarToggleSwitch();
onProcessArguments(getArguments());
getListView().setDivider(null);
getListView().setEnabled(false);
}
@Override
public void onDestroyView() {
getActivity().getActionBar().setCustomView(null);
if (mOldActivityTitle != null) {
getActivity().getActionBar().setTitle(mOldActivityTitle);
}
mToggleSwitch.setOnBeforeCheckedChangeListener(null);
super.onDestroyView();
}
protected abstract void onPreferenceToggled(String preferenceKey, boolean enabled);
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (!TextUtils.isEmpty(mSettingsTitle) && mSettingsIntent != null) {
MenuItem menuItem = menu.add(mSettingsTitle);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menuItem.setIntent(mSettingsIntent);
}
if (!TextUtils.isEmpty(mAddPrintersTitle) && mAddPrintersIntent != null) {
MenuItem menuItem = menu.add(mAddPrintersTitle);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menuItem.setIntent(mAddPrintersIntent);
}
}
protected void onInstallActionBarToggleSwitch() {
mToggleSwitch = createAndAddActionBarToggleSwitch(getActivity());
}
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;
}
protected void onProcessArguments(Bundle arguments) {
// Key.
mPreferenceKey = arguments.getString(EXTRA_PREFERENCE_KEY);
// Enabled.
final boolean enabled = arguments.getBoolean(EXTRA_CHECKED);
mToggleSwitch.setCheckedInternal(enabled);
// Title.
PreferenceActivity activity = (PreferenceActivity) getActivity();
if (!activity.onIsMultiPane() || activity.onIsHidingHeaders()) {
mOldActivityTitle = getActivity().getTitle();
String title = arguments.getString(EXTRA_TITLE);
getActivity().getActionBar().setTitle(title);
}
}
}
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);
}
}

View File

@@ -19,13 +19,11 @@ package com.android.settings;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.RestrictionEntry;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -56,9 +54,6 @@ import android.widget.TextView;
import com.android.internal.util.ArrayUtils;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment;
import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment;
import com.android.settings.ChooseLockPattern.ChooseLockPatternFragment;
import com.android.settings.accounts.AccountSyncSettings;
import com.android.settings.accounts.AuthenticatorHelper;
import com.android.settings.accounts.ManageAccountsSettings;
@@ -77,8 +72,9 @@ import com.android.settings.inputmethod.UserDictionaryList;
import com.android.settings.location.LocationSettings;
import com.android.settings.nfc.AndroidBeam;
import com.android.settings.nfc.PaymentSettings;
import com.android.settings.print.PrintServiceSettingsFragment;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.tts.TextToSpeechSettings;
import com.android.settings.users.AppRestrictionsFragment;
import com.android.settings.users.UserSettings;
import com.android.settings.vpn2.VpnSettings;
import com.android.settings.wfd.WifiDisplaySettings;
@@ -335,7 +331,7 @@ public class Settings extends PreferenceActivity
UserSettings.class.getName(),
NotificationAccessSettings.class.getName(),
ManageAccountsSettings.class.getName(),
PrintingSettings.class.getName(),
PrintSettingsFragment.class.getName(),
TrustedCredentialsSettings.class.getName(),
PaymentSettings.class.getName(),
KeyboardLayoutPickerFragment.class.getName()
@@ -497,7 +493,9 @@ public class Settings extends PreferenceActivity
BluetoothSettings.class.getName().equals(fragmentName) ||
DreamSettings.class.getName().equals(fragmentName) ||
LocationSettings.class.getName().equals(fragmentName) ||
ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName)) {
ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName) ||
PrintSettingsFragment.class.getName().equals(fragmentName) ||
PrintServiceSettingsFragment.class.getName().equals(fragmentName)) {
intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
}

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,286 @@
/*
* 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.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Switch;
import android.widget.TextView;
import com.android.internal.content.PackageMonitor;
import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import java.util.List;
/**
* Fragment with the top level print settings.
*/
public class PrintSettingsFragment extends SettingsPreferenceFragment implements DialogCreatable {
static final char ENABLED_PRINT_SERVICES_SEPARATOR = ':';
// 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";
private final PackageMonitor mSettingsPackageMonitor = new SettingsPackageMonitor();
private final Handler mHandler = new Handler() {
@Override
public void dispatchMessage(Message msg) {
updateServicesPreferences();
}
};
private final SettingsContentObserver mSettingsContentObserver =
new SettingsContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
updateServicesPreferences();
}
};
private Preference mNoServicesMessagePreference;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.print_settings);
getActivity().getActionBar().setTitle(R.string.print_settings_title);
}
@Override
public void onResume() {
super.onResume();
mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
mSettingsContentObserver.register(getContentResolver());
updateServicesPreferences();
setHasOptionsMenu(true);
}
@Override
public void onPause() {
mSettingsPackageMonitor.unregister();
mSettingsContentObserver.unregister(getContentResolver());
super.onPause();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.print_settings, menu);
MenuItem menuItem = menu.findItem(R.id.print_menu_item_download_print_service);
menuItem.setIntent(new Intent(Intent.ACTION_VIEW,
Uri.parse(getString(R.string.download_print_service_query))));
}
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();
List<ComponentName> enabledServices = SettingsUtils
.readEnabledPrintServices(getActivity());
List<ResolveInfo> installedServices = getActivity().getPackageManager()
.queryIntentServices(
new Intent(android.printservice.PrintService.SERVICE_INTERFACE),
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
final int installedServiceCount = installedServices.size();
for (int i = 0; i < installedServiceCount; i++) {
ResolveInfo installedService = installedServices.get(i);
PreferenceScreen preference = getPreferenceManager().createPreferenceScreen(
getActivity());
String title = installedService.loadLabel(getPackageManager()).toString();
preference.setTitle(title);
ComponentName componentName = new ComponentName(
installedService.serviceInfo.packageName,
installedService.serviceInfo.name);
preference.setKey(componentName.flattenToString());
preference.setOrder(i);
preference.setFragment(PrintServiceSettingsFragment.class.getName());
preference.setPersistent(false);
final boolean serviceEnabled = enabledServices.contains(componentName);
if (serviceEnabled) {
preference.setSummary(getString(R.string.print_feature_state_on));
} else {
preference.setSummary(getString(R.string.print_feature_state_off));
}
Bundle extras = preference.getExtras();
extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey());
extras.putBoolean(EXTRA_CHECKED, serviceEnabled);
extras.putString(EXTRA_TITLE, title);
PrintServiceInfo printServiceInfo = PrintServiceInfo.create(
installedService, getActivity());
CharSequence applicationLabel = installedService.loadLabel(getPackageManager());
extras.putString(EXTRA_ENABLE_WARNING_TITLE, getString(
R.string.print_service_security_warning_title, applicationLabel));
extras.putString(EXTRA_ENABLE_WARNING_MESSAGE, getString(
R.string.print_service_security_warning_summary, applicationLabel));
String settingsClassName = printServiceInfo.getSettingsActivityName();
if (!TextUtils.isEmpty(settingsClassName)) {
extras.putString(EXTRA_SETTINGS_TITLE,
getString(R.string.print_menu_item_settings));
extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
new ComponentName(installedService.serviceInfo.packageName,
settingsClassName).flattenToString());
}
String addPrinterClassName = printServiceInfo.getAddPrintersActivityName();
if (!TextUtils.isEmpty(addPrinterClassName)) {
extras.putString(EXTRA_ADD_PRINTERS_TITLE,
getString(R.string.print_menu_item_add_printers));
extras.putString(EXTRA_ADD_PRINTERS_COMPONENT_NAME,
new ComponentName(installedService.serviceInfo.packageName,
addPrinterClassName).flattenToString());
}
extras.putString(EXTRA_SERVICE_COMPONENT_NAME, componentName.flattenToString());
getPreferenceScreen().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);
}
}
private class SettingsPackageMonitor extends PackageMonitor {
@Override
public void onPackageAdded(String packageName, int uid) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageAppeared(String packageName, int reason) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageDisappeared(String packageName, int reason) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageRemoved(String packageName, int uid) {
mHandler.obtainMessage().sendToTarget();
}
}
public static class ToggleSwitch extends Switch {
private OnBeforeCheckedChangeListener mOnBeforeListener;
public static interface OnBeforeCheckedChangeListener {
public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked);
}
public ToggleSwitch(Context context) {
super(context);
}
public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) {
mOnBeforeListener = listener;
}
@Override
public void setChecked(boolean checked) {
if (mOnBeforeListener != null
&& mOnBeforeListener.onBeforeCheckedChanged(this, checked)) {
return;
}
super.setChecked(checked);
}
public void setCheckedInternal(boolean checked) {
super.setChecked(checked);
}
}
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);
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.content.ComponentName;
import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils.SimpleStringSplitter;
import java.util.ArrayList;import java.util.List;
/**
* Helper methods for reading and writing to print settings.
*/
public class SettingsUtils {
private static final char ENABLED_PRINT_SERVICES_SEPARATOR = ':';
private SettingsUtils() {
/* do nothing */
}
public static List<ComponentName> readEnabledPrintServices(Context context) {
List<ComponentName> enabledServices = new ArrayList<ComponentName>();
String enabledServicesSetting = Settings.Secure.getString(context
.getContentResolver(), Settings.Secure.ENABLED_PRINT_SERVICES);
if (enabledServicesSetting == null) {
return enabledServices;
}
SimpleStringSplitter colonSplitter = new SimpleStringSplitter(
ENABLED_PRINT_SERVICES_SEPARATOR);
colonSplitter.setString(enabledServicesSetting);
while (colonSplitter.hasNext()) {
String componentNameString = colonSplitter.next();
ComponentName enabledService = ComponentName.unflattenFromString(
componentNameString);
enabledServices.add(enabledService);
}
return enabledServices;
}
public static void writeEnabledPrintServices(Context context,
List<ComponentName> services) {
StringBuilder builder = new StringBuilder();
final int serviceCount = services.size();
for (int i = 0; i < serviceCount; i++) {
ComponentName service = services.get(i);
if (builder.length() > 0) {
builder.append(ENABLED_PRINT_SERVICES_SEPARATOR);
}
builder.append(service.flattenToString());
}
Settings.Secure.putString(context.getContentResolver(),
Settings.Secure.ENABLED_PRINT_SERVICES,
builder.toString());
}
}