Back to project page qrcode-android.
The source code is released under:
MIT License
If you think the Android project qrcode-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2013 ZXing authors/*w w w .j a v a 2 s . c om*/ * * 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.google.zxing.client.android; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.util.Log; import com.google.zxing.DecodeHintType; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; /** * @author Lachezar Dobrev */ final class DecodeHintManager { private static final String TAG = DecodeHintManager.class.getSimpleName(); // This pattern is used in decoding integer arrays. private static final Pattern COMMA = Pattern.compile(","); private DecodeHintManager() { } /** * <p>Split a query string into a list of name-value pairs.</p> * <p/> * <p>This is an alternative to the {@link Uri#getQueryParameterNames()} and * {@link Uri#getQueryParameters(String)}, which are quirky and not suitable * for exist-only Uri parameters.</p> * <p/> * <p>This method ignores multiple parameters with the same name and returns the * first one only. This is technically incorrect, but should be acceptable due * to the method of processing Hints: no multiple values for a hint.</p> * * @param query query to split * @return name-value pairs */ private static Map<String, String> splitQuery(String query) { Map<String, String> map = new HashMap<String, String>(); int pos = 0; while (pos < query.length()) { if (query.charAt(pos) == '&') { // Skip consecutive ampersand separators. pos++; continue; } int amp = query.indexOf('&', pos); int equ = query.indexOf('=', pos); if (amp < 0) { // This is the last element in the query, no more ampersand elements. String name; String text; if (equ < 0) { // No equal sign name = query.substring(pos); name = name.replace('+', ' '); // Preemptively decode + name = Uri.decode(name); text = ""; } else { // Split name and text. name = query.substring(pos, equ); name = name.replace('+', ' '); // Preemptively decode + name = Uri.decode(name); text = query.substring(equ + 1); text = text.replace('+', ' '); // Preemptively decode + text = Uri.decode(text); } if (!map.containsKey(name)) { map.put(name, text); } break; } if (equ < 0 || equ > amp) { // No equal sign until the &: this is a simple parameter with no value. String name = query.substring(pos, amp); name = name.replace('+', ' '); // Preemptively decode + name = Uri.decode(name); if (!map.containsKey(name)) { map.put(name, ""); } pos = amp + 1; continue; } String name = query.substring(pos, equ); name = name.replace('+', ' '); // Preemptively decode + name = Uri.decode(name); String text = query.substring(equ + 1, amp); text = text.replace('+', ' '); // Preemptively decode + text = Uri.decode(text); if (!map.containsKey(name)) { map.put(name, text); } pos = amp + 1; } return map; } static Map<DecodeHintType, ?> parseDecodeHints(Uri inputUri) { String query = inputUri.getEncodedQuery(); if (query == null || query.length() == 0) { return null; } // Extract parameters Map<String, String> parameters = splitQuery(query); Map<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class); for (DecodeHintType hintType : DecodeHintType.values()) { if (hintType == DecodeHintType.CHARACTER_SET || hintType == DecodeHintType.NEED_RESULT_POINT_CALLBACK || hintType == DecodeHintType.POSSIBLE_FORMATS) { continue; // This hint is specified in another way } String parameterName = hintType.name(); String parameterText = parameters.get(parameterName); if (parameterText == null) { continue; } if (hintType.getValueType().equals(Object.class)) { // This is an unspecified type of hint content. Use the value as is. // TODO: Can we make a different assumption on this? hints.put(hintType, parameterText); continue; } if (hintType.getValueType().equals(Void.class)) { // Void hints are just flags: use the constant specified by DecodeHintType hints.put(hintType, Boolean.TRUE); continue; } if (hintType.getValueType().equals(String.class)) { // A string hint: use the decoded value. hints.put(hintType, parameterText); continue; } if (hintType.getValueType().equals(Boolean.class)) { // A boolean hint: a few values for false, everything else is true. // An empty parameter is simply a flag-style parameter, assuming true if (parameterText.length() == 0) { hints.put(hintType, Boolean.TRUE); } else if ("0".equals(parameterText) || "false".equalsIgnoreCase(parameterText) || "no".equalsIgnoreCase(parameterText)) { hints.put(hintType, Boolean.FALSE); } else { hints.put(hintType, Boolean.TRUE); } continue; } if (hintType.getValueType().equals(int[].class)) { // An integer array. Used to specify valid lengths. // Strip a trailing comma as in Java style array initialisers. if (parameterText.length() > 0 && parameterText.charAt(parameterText.length() - 1) == ',') { parameterText = parameterText.substring(0, parameterText.length() - 1); } String[] values = COMMA.split(parameterText); int[] array = new int[values.length]; for (int i = 0; i < values.length; i++) { try { array[i] = Integer.parseInt(values[i]); } catch (NumberFormatException ignored) { Log.w(TAG, "Skipping array of integers hint " + hintType + " due to invalid numeric value: '" + values[i] + '\''); array = null; break; } } if (array != null) { hints.put(hintType, array); } continue; } Log.w(TAG, "Unsupported hint type '" + hintType + "' of type " + hintType.getValueType()); } Log.i(TAG, "Hints from the URI: " + hints); return hints; } static Map<DecodeHintType, Object> parseDecodeHints(Intent intent) { Bundle extras = intent.getExtras(); if (extras == null || extras.isEmpty()) { return null; } Map<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class); for (DecodeHintType hintType : DecodeHintType.values()) { if (hintType == DecodeHintType.CHARACTER_SET || hintType == DecodeHintType.NEED_RESULT_POINT_CALLBACK || hintType == DecodeHintType.POSSIBLE_FORMATS) { continue; // This hint is specified in another way } String hintName = hintType.name(); if (extras.containsKey(hintName)) { if (hintType.getValueType().equals(Void.class)) { // Void hints are just flags: use the constant specified by the DecodeHintType hints.put(hintType, Boolean.TRUE); } else { Object hintData = extras.get(hintName); if (hintType.getValueType().isInstance(hintData)) { hints.put(hintType, hintData); } else { Log.w(TAG, "Ignoring hint " + hintType + " because it is not assignable from " + hintData); } } } } Log.i(TAG, "Hints from the Intent: " + hints); return hints; } }