Google GeoLocation API returns different results for the same wifi access point - google-geolocation

We are using Google's geolocation API to get the latlong for the wifi access points. We are seeing inconsistent results. Google's API returns different latlong on different boxes. When I test on my development box, I get the latlong which points to a location in US. When I test the same on the amazon ec2 box, I get the latlong which points to a location in Japan. Has anybody else experienced the same with Google's GeoLocation API?
Below is the code and the response strings from both hosts. JDK and JSON jar version is same on both the hosts.
public void testWifiIdMappingApi() {
String apiUrl = "https://www.googleapis.com/geolocation/v1/geolocate?key=xxxxxxxxxxxxxxxxxxxxxxxx";
InputStream inputStream = null;
HttpsURLConnection con = null;
DataOutputStream wr = null;
try {
URL url = new URL(apiUrl);
con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setDoInput(true);
con.setDoOutput(true);
con.connect();
JSONObject obj = new JSONObject();
JSONArray wifiAry = new JSONArray();
JSONObject wifiObj = new JSONObject();
wifiObj.put("macAddress", "6c:f3:7f:4b:37:74");
wifiObj.put("signalStrength", 60);
wifiAry.add(wifiObj);
wifiObj = new JSONObject();
wifiObj.put("macAddress", "6c:f3:7f:4b:37:75");
wifiObj.put("signalStrength", 60);
wifiAry.add(wifiObj);
obj.put("wifiAccessPoints", wifiAry);
System.out.println(obj.toString());
wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(obj.toString());
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
inputStream = null;
if (responseCode == HttpsURLConnection.HTTP_OK) {
inputStream = con.getInputStream();
} else {
inputStream = con.getErrorStream();
}
final char[] buffer = new char[4096];
StringBuilder response = new StringBuilder();
Reader r = new InputStreamReader(inputStream, "UTF-8");
int read;
do {
read = r.read(buffer, 0, buffer.length);
if (read > 0) {
response.append(buffer, 0, read);
}
} while (read >= 0);
System.out.println(new java.util.Date() + " - "
+ response.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null)
inputStream.close();
if (wr != null)
wr.close();
if (con != null)
con.disconnect();
} catch (Exception e) {
}
}
}
Input JSON String
{"wifiAccessPoints":[{"signalStrength":60,"macAddress":"6c:f3:7f:4b:37:74"},
{"signalStrength":60,"macAddress":"6c:f3:7f:4b:37:75"}]}
Response on the amazon ec2 host
{
"location": {
"lat": 40.603124,
"lng": 140.463922
},
"accuracy": 122000.0
}
Response on my development box (windows 7)
{
"location": {
"lat": 37.593392,
"lng": -122.04383
},
"accuracy": 22000.0
}

You might want to pass the considerIp field as False in your POST body. This would be what Google determines to be your location when the wifi routers aren't doing their job.

Related

Get document from GET request

I need your help:
I have the following method
#Path("/download")
public class FileDownloadService {
#GET
public Response downloadFile(#QueryParam("filenet_id") String filenet_id, #QueryParam("version") String version) {
...
Document document = (Document) cmisObject;
return Response.ok(document, MediaType.APPLICATION_OCTET_STREAM).build();
}
and I want to get the document throught HTTP GET, I tried to write this code but I don't know how to get it, "output" don't conatains it:
URIBuilder builder = new URIBuilder();
builder.setScheme("http").setHost("localhost:8080").setPath("/filenetintegration/rest/download")
.setParameter("filenet_id", filenet_id)
.setParameter("version", version+".0");
URI uri = builder.build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
HttpURLConnection urlConnection = (HttpURLConnection) new URL(uri.toString()).openConnection();
urlConnection.connect();
BufferedReader br = new BufferedReader(new InputStreamReader((urlConnection.getInputStream())));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
Edit:
maybe the problem is on this line, it don't put the document inside the response:
return Response.ok(document, MediaType.APPLICATION_OCTET_STREAM).build();
You need something like this on the server side:
Document document = (Document) cmisObject;
ContentStream contentStream = document.getContentStream();
final InputStream stream = contentStream.getStream();
StreamingOutput output = (OutputStream out) -> {
try {
int b;
byte[] buffer = new byte[64*1024];
while ((b = stream.read(buffer)) > -1) {
out.write(buffer, 0, b);
}
} finally {
try {
stream.close();
} catch (IOException ioe) {}
}
};
return Response.ok(output, contentStream.getMimeType()).build();

Why am I getting a "NotSupportedException" with this code?

I am trying to call a Web API method from a handheld device (Compact Framework) with this code:
// "fullFilePath" is a value such as "\Program Files\Bla\abc.xml"
// "uri" is something like "http://localhost:28642/api/ControllerName/PostArgsAndXMLFile?serialNum=8675309&siteNum=42"
SendXMLFile(fullFilePath, uri, 500);
. . .
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
uri = uri.Replace('\\', '/');
if (!uri.StartsWith("/"))
{
uri = "/" + uri;
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "POST";
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(xmlFilepath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());
if (timeout < 0)
{
request.ReadWriteTimeout = timeout;
request.Timeout = timeout;
}
request.ContentLength = postBytes.Length;
request.KeepAlive = false;
request.ContentType = "application/x-www-form-urlencoded"; // not "text/xml" correct?
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
using (var response = (HttpWebResponse)request.GetResponse())
{
return response.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
request.Abort();
return string.Empty;
}
}
}
Somewhere in SendXMLFile(), it is failing with "NotSupportedException" though... As it's running on a handheld device, I can't put a breakpoint in it and step through it; I could sprinkle a bunch of debug statements throughout (MessageBox.Show()), but I'd rather not do that.
The server code never even reaches the breakpoint I put on the "XDocument doc =" line below:
[Route("api/ControllerName/PostArgsAndXMLFile")]
public void PostArgsAndFile([FromBody] string stringifiedXML, string serialNum, string siteNum)
{
XDocument doc = XDocument.Parse(stringifiedXML);
Is it that the Compact framework can't call a (RESTful) Web API method for some reason? Obviously, the client (handheld/Compact Framework) compiles and runs, it just refuses to actually follow through with the runtime realities of it all.
Does my code require a small alteration for it to fit, or do I need to take a completely different tack?
Web API is not going to be able to handle your body content. You declared it as application/x-form-urlencoded, but it is actually XML formatted and your method signature is expecting it to be a XMLDataContract serialized string.
Instead of using the parameter stringifiedXML, instead, just read the body inside your method..
[Route("api/ControllerName/PostArgsAndXMLFile")]
public async void PostArgsAndFile(string serialNum, string siteNum)
{
XDocument doc = XDocument.Parse(await Request.Content.ReadAsStringAsync());
}
Or event better, use a stream directly.
[Route("api/ControllerName/PostArgsAndXMLFile")]
public async void PostArgsAndFile(string serialNum, string siteNum)
{
XDocument doc = XDocument.Load(await Request.Content.ReadAsStreamAsync());
}
This way, you can put the ContentType on the client back to application/xml as it should be.
Using Darrel's code on the server side (I'm using the second one, the Stream), this works on the Client side:
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/xml";
request.Method = "POST";
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(xmlFilepath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());
if (timeout < 0)
{
request.ReadWriteTimeout = timeout;
request.Timeout = timeout;
}
request.ContentLength = postBytes.Length;
request.KeepAlive = false;
request.ContentType = "application/x-www-form-urlencoded";
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
using (var response = (HttpWebResponse)request.GetResponse())
{
return response.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
request.Abort();
return string.Empty;
}
}
}
Which can be called like so:
private void buttonNose_Click(object sender, EventArgs e)
{
String fullFilePath = #"C:\McMurtry\LonesomeDove.XML";
String uri = #"http://localhost:21608/api/inventory/sendxml/ff/gg/42";
SendXMLFile(fullFilePath, uri, 500);
}

BlackBerry - Downloaded images are corrupted on wifi with HttpConnection

In my app I need to download several images from a server. I use this code to get a byte array :
HttpConnection connection = null;
InputStream inputStream = null;
byte[] data = null;
try
{
//connection = (HttpConnection)Connector.open(url);
connection = (HttpConnection)Connector.open(url, Connector.READ_WRITE, true);
int responseCode = connection.getResponseCode();
if(responseCode == HttpConnection.HTTP_OK)
{
inputStream = connection.openInputStream();
data = IOUtilities.streamToBytes(inputStream);
inputStream.close();
}
connection.close();
return data;
}
catch(IOException e)
{
return null;
}
The url are formed with the suffix ";deviceSide=false;ConnectionType=MDS - public" (without spaces) and it is working perfectly well.
The problem is that with phones that do not have a sim card, we can't connect to the internet via the MDS server. So we changed to use the connection factory and let BB choose whatever he wants :
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(url);
if (connDesc != null)
{
final HttpConnection httpConn;
httpConn = (HttpConnection)connDesc.getConnection();
try
{
httpConn.setRequestMethod(HttpConnection.GET);
final int iResponseCode = httpConn.getResponseCode();
if(iResponseCode == HttpConnection.HTTP_OK)
{
InputStream inputStream = null;
try{
inputStream = httpConn.openInputStream();
byte[] data = IOUtilities.streamToBytes(inputStream);
return data;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
finally{
try
{
inputStream.close();
} catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
}
catch (IOException e)
{
System.err.println("Caught IOException: " + e.getMessage());
}
}
return null;
The connection works because it select the good prefix (interface=wifi in our case), but this create another problem.
Some images are not well downloaded, some of them (not the sames at each try) are corrupted, but only when the phone use a wifi connection to get these images.
How can I avoid this problem ? What method to get a connection do I have to use ? Is it possible to check if the user have a sim card in orderto use MDS - public ?
Here is an example of a corrupted image :
error image http://nsa30.casimages.com/img/2012/06/28/120628033716123822.png
try this:
public static String buildURL(String url) {
String connParams = "";
if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
connParams = ";interface=wifi"; //Connected to a WiFi access point.
} else {
int coverageStatus = CoverageInfo.getCoverageStatus();
//
if ((coverageStatus & CoverageInfo.COVERAGE_BIS_B) == CoverageInfo.COVERAGE_BIS_B) {
connParams = ";deviceside=false;ConnectionType=mds-public";
} else if ((coverageStatus & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT) {
// Have network coverage and a WAP 2.0 service book record
ServiceRecord record = getWAP2ServiceRecord();
//
if (record != null) {
connParams = ";deviceside=true;ConnectionUID=" + record.getUid();
} else {
connParams = ";deviceside=true";
}
} else if ((coverageStatus & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS) {
// Have an MDS service book and network coverage
connParams = ";deviceside=false";
}
}
Log.d("connection param"+url+connParams);
//
return url+connParams;
}
private static ServiceRecord getWAP2ServiceRecord() {
String cid;
String uid;
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.getRecords();
//
for (int i = records.length -1; i >= 0; i--) {
cid = records[i].getCid().toLowerCase();
uid = records[i].getUid().toLowerCase();
//
if (cid.indexOf("wptcp") != -1
&& records[i].getUid().toLowerCase().indexOf("wap2") !=-1
&& uid.indexOf("wifi") == -1
&& uid.indexOf("mms") == -1) {
return records[i];
}
}
//
return null;
}
What happens when you append interface=wifi? Can you run the network diagnostic tool attached to below kb article and run all tests with SIM removed
http://supportforums.blackberry.com/t5/Java-Development/What-Is-Network-API-alternative-for-legacy-OS/ta-p/614822
Please also note that when download large files over BES/MDS there are limits imposed by MDS. Please ensure you review the below kb article
http://supportforums.blackberry.com/t5/Java-Development/Download-large-files-using-the-BlackBerry-Mobile-Data-System/ta-p/44585
You can check to see if coverage is sufficient for BIS_B (MDS public) but that won't help you if you are trying to support SIM-less users. I wonder if the problem is in an incomparability between the connection on Wi-Fi and IOUtilities.streamToBytes(). Try coding as recommended in the API documents.

SNMP4J adding user

I've been doing some very basic SNMP4J programming. All I want to do is send a simple "get" request but so far my responses have been null. I opened up wireshark and found that in the under Simple Network Management Protocol, my msgUserName is blank and I need that to be populated.
I thought I had set it using the following code:
Snmp snmp = new Snmp(transport);
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
transport.listen();
UsmUser user = new UsmUser(new OctetString("SNMPManager"), AuthSHA.ID,new OctetString("password"),null,null);
// add user to the USM
snmp.getUSM().addUser(user.getSecurityName(), user);
Am I going about it the wrong way? If not, how do I set the msgUserName as seen in my wireshark dump of the get-request? I'm very new to SNMP, so I'm essentially running off examples.
This is a working snmpset you can write snmp get same way.Snmp4j v2 and v3 not using same api classes.
private void snmpSetV3(VariableBinding[] bindings) throws TimeOutException, OperationFailed {
Snmp snmp = null;
try {
PDU pdu = new ScopedPDU();
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.getUSM().addUser(new OctetString(Username), new UsmUser(new OctetString(Username), AuthMD5.ID, new OctetString(Password), AuthMD5.ID, null));
ScopedPDU scopedPDU = (ScopedPDU) pdu;
scopedPDU.setType(PDU.SET);
scopedPDU.addAll(bindings);
UserTarget target = new UserTarget();
target.setAddress(new UdpAddress(IPAddress + "/" + Port));
target.setVersion(version); //SnmpConstants.version3
target.setRetries(retries);
target.setTimeout(timeout);
target.setSecurityLevel(securityLevel); //SecurityLevel.AUTH_NOPRIV
target.setSecurityName(new OctetString(Username));
snmp.listen();
ResponseEvent response = snmp.send(pdu, target);
if (response.getResponse() != null) {
PDU responsePDU = response.getResponse();
if (responsePDU != null) {
if (responsePDU.getErrorStatus() == PDU.noError) {
return;
}
throw new OperationFailed("Error: Request Failed, "
+ "Error Status = " + responsePDU.getErrorStatus()
+ ", Error Index = " + responsePDU.getErrorIndex()
+ ", Error Status Text = " + responsePDU.getErrorStatusText());
}
}
throw new TimeOutException("Error: Agent Timeout... ");
} catch (IOException e) {
throw new OperationFailed(e.getMessage(), e);
} finally {
if (snmp != null) {
try {
snmp.close();
} catch (IOException ex) {
_logger.error(ex.getMessage(), ex);
}
}
}
}

Upload Image using blackberry

I want to upload an image in blackberry simulator using MultipartPostData, the following is my code but it does not seem to work. I have also signed my .cod file. Can anyone help me please?
public void postData(String Url, bytes[] data)
{
if (DeviceInfo.isSimulator()){
Url=Url+";deviceSide=true";
}
HttpConnection httpConn=null;
OutputStream os=null;
InputStream is=null;
String url=Url;
try {
PostData form = new MultipartPostData(MultipartPostData.DEFAULT_CHARSET, false) ;
byte [] postData = data;
form.setData(postData);
httpConn = (HttpConnection) Connector.open(url);
httpConn.setRequestMethod(HttpConnection.POST);
httpConn.setRequestProperty("User-Agent", "BlackBerry");
httpConn.setRequestProperty("Content-Type", "multipart/form-data");
httpConn.setRequestProperty("MIME-Type", "Image/Jpeg");
httpConn.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_LENGTH, String.valueOf(postData.length));
httpConn.setRequestProperty("Content-Language", "en-US");
os =httpConn.openOutputStream();
os.write(form.getBytes());
//read response
StringBuffer sb = new StringBuffer();
is = httpConn.openDataInputStream();
int chr;
while ((chr = is.read()) != -1)
sb.append((char) chr);
System.out.println("Result................................ " + sb.toString());
String result=sb.toString();
}
catch(Exception e)
{
System.out.println(e.toString());
}
finally {
try{
if(is!= null)
is.close();
if(os != null)
os.close();
if(httpConn != null)
httpConn.close();
} catch(Exception e1){
System.out.println(e1.toString());
}
}
}
//you must have a bundary format post data, the .cod file must be work on the simulator
httpConn = (HttpConnection)connDesc.getConnection();
httpConn.setRequestMethod(HttpConnection.POST);
httpConn.setRequestProperty("user-agent", "BlackBerry");
httpConn.setRequestProperty("content-type", "multipart/form-data; boundary=----------V2ymHFg03ehbqgZCaKO6jy");
os = httpConn.openOutputStream();
//os.write(form.getBytes());
byte[] fileBytes = {1,2,3,4}; //retrieve file bytes with your own code
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(("\r\n--" + "----------V2ymHFg03ehbqgZCaKO6jy" + "\r\n").getBytes());
bos.write(("Content-Disposition: form-data; name=\"mifoto\"; filename=\"leo.gif\"\r\n").getBytes());
bos.write(("Content-Type: image/gif\r\n\r\n").getBytes());
bos.write(fileBytes);
bos.write(("\r\n--" + "----------V2ymHFg03ehbqgZCaKO6jy" + "--\r\n").getBytes());
os.write(bos.toByteArray());
As soon as you call MultipartPostData.setData(), it overwrites any Content-Disposition data you have set with MultipartPostData.append().
leonel's answer works or you can use Vlad Patryshev's ClientHttpRequest class.

Resources