Android Uri query异常分析

起因

有这样一个需求 我们想把 原始uri中的scheme转换一下 你会怎么做

hehe://a/hehe?params=%7B%22url

转换成

haha://a/hehe?params=%7B%22url

直接replace显然是不合适的

经过

我们这样做

 Uri originaluri = Uri.parse("hehe://a/hehe?params=%7B%22url");
 Uri newuri = new Uri.Builder().scheme("haha")
                .authority(originaluri.getAuthority())
                .path(originaluri.getPath())
                .query(originaluri.getQuery()).build();
 Log.d("uri", newuri.toString());

看似很美好但是日志确实

haha://a/hehe?params%3D%7B%22url

可以看出query参数中的 = 被编码了 变成了%3D!
这显然不是我们想要的

分析

originaluri.getQuery()的返回结果是{"url
那我们需要分析

query(originaluri.getQuery()).build();

都做了啥?

最终会生成Part类作为uri的一个属性

new Part(encoded, decoded) 

该类存放我们query参数中的编码数据和解码数据,其中encoded = NOT_CACHED ,decoded = {"url.

build()方法会返回HierarchicalUri类 我们看看该类的toString做了啥

 String encodedAuthority = authority.getEncoded();
            if (encodedAuthority != null) {
                // Even if the authority is "", we still want to append "//".
                builder.append("//").append(encodedAuthority);
            }

            String encodedPath = path.getEncoded();
            if (encodedPath != null) {
                builder.append(encodedPath);
            }

            if (!query.isEmpty()) {
                builder.append('?').append(query.getEncoded()); //编码 把query的所有数据的编码了
            }
   String getEncoded() {
            @SuppressWarnings("StringEquality")
            boolean hasEncoded = encoded != NOT_CACHED;
            return hasEncoded ? encoded : (encoded = encode(decoded));
        }

builder.append('?').append(query.getEncoded());编码 由于没有缓存所以把query的解码数据编码了 所有 = 变成了 %3D

结果

如何解决呢?编码数据由缓存就可以了!

 Uri originaluri = Uri.parse("hehe://a/hehe?params=%7B%22url");
 Uri newuri = new Uri.Builder().scheme("haha")
                .authority(originaluri.getAuthority())
                .path(originaluri.getPath())
                .encodedQuery(originaluri.getEncodedQuery()).build();
 Log.d("uri", newuri.toString());

将 query改成encodedQuery就可以了

你可能感兴趣的:(Android Uri query异常分析)