我正在寻找一种从 android.net.Uri 获取查询参数名称的替代方法。getQueryParameterNames() 需要 api 级别 11。我想对任何较低级别的 api 做同样的事情。我正在查看 getQuery() 它将在“?”之后返回所有内容 符号。解决这个问题的最好方法是解析该字符串并在“=”之前搜索所有内容并捕获它吗?我根本不知道每次会呈现什么查询参数。
问问题
6927 次
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);
}
如果你想自己深入研究,这里是原始代码:
于 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 回答