6

android.net.Uri からクエリ パラメータ名を取得する別の方法を探しています。getQueryParameterNames() には api レベル 11 が必要です。下位レベルの api についても同じことをしたいと思います。「?」の後にすべてを返す getQuery() を見ていました。サイン。これを行う最善の方法は、その文字列を解析し、「=」の前のすべてを検索してキャプチャすることでしょうか? 毎回どのクエリ パラメータが表示されるかはわかりません。

4

4 に答える 4

13

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

于 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 を足したり引いたりして呼び出しの一部を調整する必要があるかもしれませんList。他の人が見ることができるエラーについてコメントすると思いますが、これがその一般的な要点です。;どこか忘れたような気がします。

編集: 以下に示すように、結果を LinkList の代わりに新しい ArrayList に設定します。

于 2012-07-25T04:26:29.843 に答える