所以我试图在我的Android应用程序中使用Xamarin从API(我无法控制)中获取一些信息。
它的作用很棒!如果我将生成的链接粘贴到Chrome中,或者使用Chrome扩展程序Postman,我会得到我想要的信息,但它在我的应用程序中不起作用..
应用程序处于poc状态,因此所有内容都在实现ILocationListener
的主活动中,并且每3秒请求一次gps更新,但这是代码中有趣的部分:
public void OnLocationChanged(Location location) {
var lat = location.Latitude;
var lon = location.Longitude;
_lat.Text = "lat: " + lat;
_lon.Text = "lon: " + lon;
// get the vegReference (roadReference) based on the lat & lon
var url = "https://www.vegvesen.no/nvdb/api/vegreferanse/koordinat?lon=" + lon.ToString("") + "&lat=" + lat.ToString("") + "&geometri=WGS84";
// ex: https://www.vegvesen.no/nvdb/api/vegreferanse/koordinat?lon=10.399547&lat=63.354658&geometri=WGS84
var json = new JSONObject(Get(url));
Log.Debug("url", url);
Log.Debug("json", json.ToString());
if (json.GetString("kommuneNr") == "0") return; // bug in API?
var kommuneNr = json.GetString("kommuneNr");
var vegReferanse = json.GetString("visningsNavn");
// get the object id 105 (speed limit) on set vegReference
// API dok: https://www.vegvesen.no/nvdb/apidokumentasjon/#/get/vegobjekter
var url2 = "https://www.vegvesen.no/nvdb/api/v2/vegobjekter/105?vegreferanse=" + vegReferanse.Replace(" ", "") + "&inkluder=lokasjon&segmentering=false";
// ex. https://www.vegvesen.no/nvdb/api/v2/vegobjekter/105?vegreferanse=PV3133HP1m73&inkluder=lokasjon&segmentering=false
// this (url2) is the one that fails
Log.Debug("url2", url2);
var json2 = new JSONObject(Get(url2));
Log.Debug("json2", json2.ToString());
// get the speed limit with the heighest id (this should be the latest one (FYI: speedlimits have changed over the years, all speed limits are in the database for historical reasons(?)))
var objs = json2.GetJSONArray("vegObjekter");
var list = new List<JSONObject>();
// getting a list of possible objects based on the kommuneNr (because for some f*ced up reason the result returns objects in other kommunes aswell...)
for (int i = 0; i < objs.Length() - 1; i++)
{
if (objs.GetJSONObject(i).GetJSONObject("lokasjon").GetJSONArray("kommuner").GetString(0) == kommuneNr)
list.Add(objs.GetJSONObject(i));
}
if (list.Count == 0) return;
var url3 = list[list.Count - 1].GetString("href");
// ex. https://www.vegvesen.no/nvdb/api/v2/vegobjekter/105/276790644
Log.Debug("url3", url3);
var json3 = new JSONObject(Get(url3));
Log.Debug("json3", json3.ToString());
// set the speed-limit to the textview.
var res = json3.GetJSONArray("egenskaper").GetJSONObject(0).GetString("verdi");
_tvSl.Text = res + " km/t";
}
Get
- 方法在OnLocationChanged
内部调用,基本上只是将响应作为字符串获取:
private string Get(string url)
{
var request = WebRequest.Create(url);
var sb = new StringBuilder();
var response = (HttpWebResponse)request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
sb.Append(sr.ReadToEnd());
}
return sb.ToString();
}
url2-request的响应如下:
System.Net.WebException: The remote server returned an error: (500) Internal Server Error.
我的问题是这个;为什么链接(ref url2)在浏览器中工作,而不在应用程序中工作。
任何有关此事的帮助或指示将不胜感激! 另外:链接到GitHub上的项目:https://github.com/Nemeas/alfaOmega
答案 0 :(得分:0)
好的,经过大量的试验和错误后,我发现问题在于标题丢失了; accept: application/json
(看起来这只是这个api(?)的v2的情况)。我尝试使用WebRequest
添加标题,但每当我到达添加标题的行时,我都会收到错误。但是,还有另一个WebRequest
称为HttpWebRequest
,其中accept
作为属性公开,而不是通过列表公开,这是有效的。因此,我必须做出的唯一改变是Get
方法,最终结果如下:
public static string Get(string url)
{
// casting request to HttpWebRequest to expose Accept as a property
var request = (HttpWebRequest)WebRequest.Create(url);
request.Accept = "application/json";
var sb = new StringBuilder();
// getting the response
var response = (HttpWebResponse)request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
sb.Append(sr.ReadToEnd());
}
var res = sb.ToString();
// returning the response as a string
return res;
}
答案 1 :(得分:0)
这可能取决于标头中的 user-agent
值。如果您提供类似于浏览器的用户代理值,它可能会起作用。