构建X:Y格式的Uri

时间:2014-02-10 23:12:31

标签: android uri

我正在尝试构建一个Uri,这是一种意图查询地图上某个位置的最正确方法。在地图意图的documentation中,指出Uris的格式应为:geo:0,0?q=my+street+address。我尝试使用Uri.Builder,但没有找到指定"0,0"的方法  作为Uri.Builder的uri的一部分没有指定路径的功能而没有预先加上'/'。目前我使用以下代码:

uri = new Uri.Builder()
         .scheme(URL_SCHEME_MAP)
         .encodedOpaquePart("0,0?q=" + query)
         .build();

哪个好,但不如我想要的好。所以我想知道是否有人知道更好/更好的方法来做到这一点。

5 个答案:

答案 0 :(得分:9)

正如@providencemac所指出的,Udacity Android开发课程展示了如何执行此操作,但它实际上现在使用Uri.Builder。但是,他们的代码是错误的:

Uri.Builder builder = new Uri.Builder();
builder.scheme("geo")
        .path("0,0")
        .query(streetAddr);
Uri uri = builder.build();

如果您使用Google的地址作为查询位置,就像课程一样,模拟器仍然会去那里,因为这是默认设置。但是没有位置标记,其他地址也不起作用。相反,它应该是这样的:

Uri.Builder builder = new Uri.Builder();
builder.scheme("geo")
        .appendPath("0,0")
        .appendQueryParameter("q", addressString);
Uri addressUri = builder.build();

答案 1 :(得分:7)

您可以结合使用parsebuildUpon方法来完成此操作:

Uri geoLocation = Uri.parse("geo:0,0?").buildUpon()
                .appendQueryParameter("q", location)
                .build();

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(geoLocation);

我从Udacity class "Developing Android Apps"学到了这种方法,尽管他们没有完全解释它。

答案 2 :(得分:4)

只是建立@providencemac答案并提供更多背景信息:

Java区分分层和不透明的URI。你在这里想要创建的是一个不透明的URI。这种URI由三部分组成:方案,不透明部分和片段。不透明部分基本上是方案分隔符(:)和片段分隔符(#)之间的所有内容。 那么buildUpon实际上在不透明URI的引擎下做了以下几点:

return new Builder()
    .scheme(getScheme())
    .opaquePart(getSsp())
    .fragment(getFragmentPart());

getSchemeparse设置的字符串中获取所有内容,直到:getSsp SSP 表示方案特定部分< / em>)获取:#之间的所有内容,getFragmentPart获取#之后的所有内容。

所以@ providencemac在不使用parsebuiltUpon的情况下的回答如下:

uri = new Uri.Builder()
     .scheme(URL_SCHEME_MAP)
     .encodedOpaquePart("0,0")
     .appendQueryParameter("q", query)
     .build();

可悲的是,虽然在对来源进行了一些研究时我注意到了这个以及原始答案的缺陷(因此可能是上述Udacity课程的问题)。从SDK 23rev3开始,appendQueryParameter中的前两行如下所示:

// This URI will be hierarchical.
this.opaquePart = null;

所以我们以前不透明的URI被转换为分层的URI,而不是实际上是分层的,因为它既不是相对的,也不包含"://"部分。所以结果看起来像"geo:?q=1600+Amphitheatre+Parkway%2C+CA",当没有给出具体的经度和纬度时,它会起作用。虽然如果您尝试从documentation创建第二个样本

uri = new Uri.Builder()
     .scheme("geo")
     .encodedOpaquePart("47.6,-122.3")
     .appendQueryParameter("z", "11")
     .build();

你最终会得到"geo:?z=zoom",这显然会显示当前设备的位置。

故事很长:我认为你应该坚持你最初在你的问题中提出的方式,因为它确实产生了你想要的东西。虽然你应该使用Uri.encode(query)

答案 3 :(得分:4)

对于那些仍然有这个问题的人。我认为这是最接近Udacity课程的:

builder.scheme("geo")
       .encodedPath("0,0")
       .appendQueryParameter("q",streetAddress);

您只需将Path()更改为encodedPath()

答案 4 :(得分:0)

我阅读了文档并尝试了所有答案,所以我也是。 如您在文档中所见,有4种数据uri模式可在地图上显示位置。

  1. 简单
  2. 缩放
  3. 标签
  4. 地址

这是我对所有选项的建议:

private Uri getGeoUri(double lat, double log) {
    return Uri.parse("geo:" + lat + "," + log);
}

private Uri getGeoUri(double lat, double log, int zoom) {
    return Uri.parse("geo:" + lat + "," + log + "?z=" + zoom);
}

private Uri getGeoUri(double lat, double log, String lable) {
    return Uri.parse("geo:0,0?q=" + lat + "," + log + "(" + lable + ")");
}

private Uri getGeoUri(String address) {
    return Uri.parse("geo:0,0?q=" + address);
}

这是使用方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Uri geoLocation = getGeoUri(47.6,-122.3);                     //1. simple
    //Uri geoLocation = getGeoUri(47.6,-122.3, 11);                 //2. zoom
    //Uri geoLocation = getGeoUri(34.99,-106.61, "Treasure");       //3. label
    Uri geoLocation = getGeoUri("1600 Amphitheatre Parkway ,CA");   //4. address
    openMap(geoLocation);
}

private void openMap(Uri geoLocation) {
    Intent i = new Intent(Intent.ACTION_VIEW);
    i.setData(geoLocation);
    if (i.resolveActivity(getPackageManager()) != null) {
        startActivity(i);
    }
}

一站式MainActivity。

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Uri geoLocation = getGeoUri(47.6,-122.3);                     //1. simple
    //Uri geoLocation = getGeoUri(47.6,-122.3, 11);                 //2. zoom
    //Uri geoLocation = getGeoUri(34.99,-106.61, "Treasure");       //3. label
    Uri geoLocation = getGeoUri("1600 Amphitheatre Parkway ,CA");   //4. address
    openMap(geoLocation);
}

private void openMap(Uri geoLocation) {
    Intent i = new Intent(Intent.ACTION_VIEW);
    i.setData(geoLocation);
    if (i.resolveActivity(getPackageManager()) != null) {
        startActivity(i);
    }
}

private Uri getGeoUri(double lat, double log) {
    return Uri.parse("geo:" + lat + "," + log);
}

private Uri getGeoUri(double lat, double log, int zoom) {
    return Uri.parse("geo:" + lat + "," + log + "?z=" + zoom);
}

private Uri getGeoUri(double lat, double log, String lable) {
    return Uri.parse("geo:0,0?q=" + lat + "," + log + "(" + lable + ")");
}

private Uri getGeoUri(String address) {
    return Uri.parse("geo:0,0?q=" + address);
}
}

享受吧。