• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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