1 /* 2 * Copyright (C) 2013 ZXing authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.zxing.client.android; 18 19 import java.net.URI; 20 import java.net.URISyntaxException; 21 import java.util.ArrayList; 22 import java.util.Collection; 23 24 import android.app.AlertDialog; 25 import android.content.SharedPreferences; 26 import android.os.Bundle; 27 import android.preference.CheckBoxPreference; 28 import android.preference.EditTextPreference; 29 import android.preference.Preference; 30 import android.preference.PreferenceFragment; 31 import android.preference.PreferenceScreen; 32 33 /** 34 * Implements support for barcode scanning preferences. 35 * 36 * @see PreferencesActivity 37 */ 38 public final class PreferencesFragment 39 extends PreferenceFragment 40 implements SharedPreferences.OnSharedPreferenceChangeListener { 41 42 private CheckBoxPreference[] checkBoxPrefs; 43 44 @Override onCreate(Bundle icicle)45 public void onCreate(Bundle icicle) { 46 super.onCreate(icicle); 47 addPreferencesFromResource(R.xml.preferences); 48 49 PreferenceScreen preferences = getPreferenceScreen(); 50 preferences.getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 51 checkBoxPrefs = findDecodePrefs(preferences, 52 PreferencesActivity.KEY_DECODE_1D_PRODUCT, 53 PreferencesActivity.KEY_DECODE_1D_INDUSTRIAL, 54 PreferencesActivity.KEY_DECODE_QR, 55 PreferencesActivity.KEY_DECODE_DATA_MATRIX, 56 PreferencesActivity.KEY_DECODE_AZTEC, 57 PreferencesActivity.KEY_DECODE_PDF417); 58 disableLastCheckedPref(); 59 60 EditTextPreference customProductSearch = (EditTextPreference) 61 preferences.findPreference(PreferencesActivity.KEY_CUSTOM_PRODUCT_SEARCH); 62 customProductSearch.setOnPreferenceChangeListener(new CustomSearchURLValidator()); 63 } 64 findDecodePrefs(PreferenceScreen preferences, String... keys)65 private static CheckBoxPreference[] findDecodePrefs(PreferenceScreen preferences, String... keys) { 66 CheckBoxPreference[] prefs = new CheckBoxPreference[keys.length]; 67 for (int i = 0; i < keys.length; i++) { 68 prefs[i] = (CheckBoxPreference) preferences.findPreference(keys[i]); 69 } 70 return prefs; 71 } 72 73 @Override onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)74 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 75 disableLastCheckedPref(); 76 } 77 disableLastCheckedPref()78 private void disableLastCheckedPref() { 79 Collection<CheckBoxPreference> checked = new ArrayList<>(checkBoxPrefs.length); 80 for (CheckBoxPreference pref : checkBoxPrefs) { 81 if (pref.isChecked()) { 82 checked.add(pref); 83 } 84 } 85 boolean disable = checked.size() <= 1; 86 for (CheckBoxPreference pref : checkBoxPrefs) { 87 pref.setEnabled(!(disable && checked.contains(pref))); 88 } 89 } 90 91 private final class CustomSearchURLValidator implements Preference.OnPreferenceChangeListener { 92 @Override onPreferenceChange(Preference preference, Object newValue)93 public boolean onPreferenceChange(Preference preference, Object newValue) { 94 if (!isValid(newValue)) { 95 AlertDialog.Builder builder = 96 new AlertDialog.Builder(PreferencesFragment.this.getActivity()); 97 builder.setTitle(R.string.msg_error); 98 builder.setMessage(R.string.msg_invalid_value); 99 builder.setCancelable(true); 100 builder.show(); 101 return false; 102 } 103 return true; 104 } 105 isValid(Object newValue)106 private boolean isValid(Object newValue) { 107 // Allow empty/null value 108 if (newValue == null) { 109 return true; 110 } 111 String valueString = newValue.toString(); 112 if (valueString.isEmpty()) { 113 return true; 114 } 115 // Before validating, remove custom placeholders, which will not 116 // be considered valid parts of the URL in some locations: 117 // Blank %t and %s: 118 valueString = valueString.replaceAll("%[st]", ""); 119 // Blank %f but not if followed by digit or a-f as it may be a hex sequence 120 valueString = valueString.replaceAll("%f(?![0-9a-f])", ""); 121 // Require a scheme otherwise: 122 try { 123 URI uri = new URI(valueString); 124 return uri.getScheme() != null; 125 } catch (URISyntaxException use) { 126 return false; 127 } 128 } 129 } 130 131 } 132