6

我正在寻找一种从 android.net.Uri 获取查询参数名称的替代方法。getQueryParameterNames() 需要 api 级别 11。我想对任何较低级别的 api 做同样的事情。我正在查看 getQuery() 它将在“?”之后返回所有内容 符号。解决这个问题的最好方法是解析该字符串并在“=”之前搜索所有内容并捕获它吗?我根本不知道每次会呈现什么查询参数。

4

4 回答 4

13

APIs < 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

于 2012-08-22T21:01:03.110 回答
4

如果您有一个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());
}
于 2014-06-05T21:23:43.570 回答
2

我同意 foxter 的观点,最好的选择是从最新的 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);
    }
}
于 2012-11-29T17:42:32.080 回答
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 来调整一些调用。另外我可能忘记了添加到 a 的确切语法List。我想评论任何错误供其他人查看,但这是它的一般要点。我有一种感觉,我忘记了;某个地方。

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

于 2012-07-25T04:26:29.843 回答