android.net.uri getQueryParameterNames()替代方案

时间:2012-07-25 03:58:00

标签: android api parameters uri

我正在寻找另一种从android.net.Uri获取查询参数名称的方法。 getQueryParameterNames()需要api级别11.我想对任何低级api做同样的事情。 我在看getQuery(),它会返回'?'之后的所有内容。标志。最好的解决方法是解析该字符串并在'='之前搜索所有内容并捕获它吗?我根本不知道每次都会显示什么查询参数。

4 个答案:

答案 0 :(得分:12)

API的唯一问题<图11的实施例是没有实现该方法。我想最好的想法是查看Android源代码并使用API​​> = 11的实现。即使在较旧的API上,这也应该让您获得绝对的功能。

这个来自4.1.1,修改后将Uri作为参数,所以你可以马上使用它:

/**
 * Returns a set of the unique names of all query parameters. Iterating
 * over the set will return the names in order of their first occurrence.
 *
 * @throws UnsupportedOperationException if this isn't a hierarchical URI
 *
 * @return a set of decoded names
 */
private Set<String> getQueryParameterNames(Uri uri) {
    if (uri.isOpaque()) {
        throw new UnsupportedOperationException("This isn't a hierarchical URI.");
    }

    String query = uri.getEncodedQuery();
    if (query == null) {
        return Collections.emptySet();
    }

    Set<String> names = new LinkedHashSet<String>();
    int start = 0;
    do {
        int next = query.indexOf('&', start);
        int end = (next == -1) ? query.length() : next;

        int separator = query.indexOf('=', start);
        if (separator > end || separator == -1) {
            separator = end;
        }

        String name = query.substring(start, separator);
        names.add(Uri.decode(name));

        // Move start to end of name.
        start = end + 1;
    } while (start < query.length());

    return Collections.unmodifiableSet(names);
}

如果你想自己深入研究,这是原始代码:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/net/Uri.java?av=f

答案 1 :(得分:3)

如果您有java.net.URI(或创建一个),则可以使用URLEncodedUtils.parse将参数和值设为NameValuePair

Map<String, String> parameters = Maps.newHashMap();
List<NameValuePair> params = URLEncodedUtils.parse(uri, "UTF-8");
for (NameValuePair param : params) {
    parameters.put(param.getName(), param.getValue());
}

答案 2 :(得分:2)

我同意福克斯的观点,最好的选择是从最新的Android版本中获取代码并添加到您的代码库中。每次我遇到这样的问题时,我都会创建一个抽象版本特性的方法。它是这样的:

public class FWCompat {
    public static boolean isFroyo_8_OrNewer() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
    }
    public static boolean isGingerbread_9_OrNewer() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
    }
    public static boolean isHoneycomb_11_OrNewer() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
    }
    public static boolean isHoneycomb_13_OrNewer() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2;
    }
    public static boolean isJellyBean_16_OrNewer() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
    }
}

@SuppressLint("NewApi")
public class FWUriCompat {

    public static Set<String> getQueryParameterNames(Uri uri) {
        if (FWCompat.isHoneycomb_11_OrNewer()) {
            return uri.getQueryParameterNames();
        }

        return FW_getQueryParameterNames(uri);
    }

    private static Set<String> FW_getQueryParameterNames(Uri uri) {
        if (uri == null) {
            throw new InvalidParameterException("Can't get parameter from a null Uri");
        }

        if (uri.isOpaque()) {
            throw new UnsupportedOperationException("This isn't a hierarchical URI.");
        }

        String query = uri.getEncodedQuery();
        if (query == null) {
            return Collections.emptySet();
        }

        Set<String> names = new LinkedHashSet<String>();
        int start = 0;
        do {
            int next = query.indexOf('&', start);
            int end = (next == -1) ? query.length() : next;

            int separator = query.indexOf('=', start);
            if (separator > end || separator == -1) {
                separator = end;
            }

            String name = query.substring(start, separator);
            names.add(Uri.decode(name));

            // Move start to end of name.
            start = end + 1;
        } while (start < query.length());

        return Collections.unmodifiableSet(names);
    }
}

答案 3 :(得分:1)

好的,这就是我想出来的。没有编译或测试它,所以没有保证

ArrayList<String> getQueryParamNames(String input) 
{
    ArrayList<String> result = new ArrayList<String>();
    //If its everything after the ? then up to the first = is the first parameter
    int start = 0;
    int end = input.indexOf("=");

    if (end == -1) return null; //No parameters in string

    while (end != -1)
    {
        result.Add(input.substring(start, end)); //May need to do end - 1 to remove the =
        //Look for next parameter, again may need to add 1 to this result to get rid of the &
        start = input.indexOf("&", end); 
        if (start == -1) //No more parameters
            break;

        //If you want to grab the values you can do so here by doing
        //input.substring(end, start);

        end = input.indexOf("=", start);
    }
    return result;  
}

我是在深夜编写的,没有对其进行测试,因此您可能需要通过添加或减去1来调整一些调用。此外,我可能忘记了添加到List的确切语法。我想评论其他人看到的任何错误,但这是它的一般要点。我有一种感觉,我在某个地方忘记了;

编辑:将结果设置为新的ArrayList而不是LinkList,如下所示