I made an app that syncs data data across devices based on an epoch time. I am currently getting this epoch time by using rest api on a server by using httpurlconnection as follows:
public static String getTime(String time){
InputStream is = null;
BufferedReader bufferedReader = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(SERVERURL);
urlConnection = (HttpURLConnection) url.openConnection();
is = urlConnection.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(is,"UTF-8"));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while((line = bufferedReader.readLine()) != null){
stringBuilder.append(line);
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
return jsonObject.getString("time");
}
catch(JSONException e){
Log.d("getTime","json object creation failed");
}
catch(IOException e){
Log.d("getTime", "couldn't get time from server");
}
finally {
try {
if(urlConnection != null){
urlConnection.disconnect();
}
if(bufferedReader != null) {
bufferedReader.close();
}
if(is != null){
is.close();
}
}
catch(IOException e){
Log.d("async getGameName","io exception closing buffer");
}
}
return time;
}
so that all devices are getting a timestamp from one known source. This method runs in a background service so it does not slows down the app responsiveness, but it is not yielding a good user experience because I need this timestamp to display information to the user and the http request takes long. Some times up to a minute because this depends on the network connectivity, so I wanted to ask if local epoch time is the same across all android devices and if it is what is the best way to get an epoch timestamp on android? Thanks in advance.
The epoch time depends on the time synchronization of a device, so two devices might have different values for it.
Also, fetching time information from a REST endpoint does not seem like the most efficient way, as you are also introducing potential delays on the API endpoint in addition to general network latency.
Since Android devices use an NTP server of sorts to get their time, why don't you get time information from the device itself and converting to epoch? The device itself is already getting updated time information so you might just as well use that.
If you want to get the current epoch value from the device itself you can use [currentTimeMillis()][1]:
System.currentTimeMillis()/1000
This returns the number of milliseconds, so to get an epoch value, which is in seconds, just divide by 1000.
Related
I have used map in my android application. I passed origin and destination latlon and get data from map url then parse the response.
But while auditing below code as marked for DOS attack stating that "This code might allow an attacker to crash the program or otherwise make it unavailable to legitimate users."
Concern : What if attacker push too large file then it will go on line by line and loop will be run for too long.
Proposed solution : Do not allow to read more than specific file size, so that it won't read file beyond some limit
Here is my code :
String url = "https://maps.googleapis.com/maps/api/directions/json"+ "?" + str_origin + "&" + str_dest + "&" + "sensor=false";
private String downloadDataFromUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpsURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.connect();
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream),1024);
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
Log.d("Exception", e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
Please provide solution. Thanks in advance.
Edit 1:by calling append() it appends Untrusted data to a StringBuilder instance initialized with the default backing-array size (16). This can cause the JVM to over-consume heap memory space.
If you download from an unknown URL, the data can indeed be arbitrary and BufferedReader.readLine() can encounter a line so long the program cannot handle it. This question indicates that limiting BufferedReader line length may not be trivial.
Number of lines can be too big as well, in which case line count check instead of simple null check in the while loop seems to be enough.
Question is why would you allow the user to input an arbitrary URL and download it without checking. The URL can easily be a several GB binary file. Your first line indicates that you intend to use the Google Maps API, which AFAIK does not return excessively large lines, rendering the DOS concern moot (except in some ultrasecure applications, which I do not think Android is suitable to use for).
I want to do a chat application and I found this code on GitHub : https://github.com/Pirngruber/AndroidIM. And author created a function to send a message which looks like this
public String sendHttpRequest(String params)
{
URL url;
String result = new String();
try
{
url = new URL(AUTHENTICATION_SERVER_ADDRESS);
HttpURLConnection connection;
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
PrintWriter out = new PrintWriter(connection.getOutputStream());
out.println(params);
out.close();
BufferedReader in = new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result = result.concat(inputLine);
}
in.close();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
if (result.length() == 0) {
result = HTTP_REQUEST_FAILED;
}
return result;
}
Where private static final String AUTHENTICATION_SERVER_ADDRESS = "http://192.168.0.102/android-im/index.php";
And also here he explained how to make it run
https://code.google.com/archive/p/simple-android-instant-messaging-application/
So, my question is that: As I understood author sends all messages to his server and after this server sends them to user. So, if PC will be turned off server won't work and his chat won't work too, is it right? If yes, can somebody explain me how to do a chat app without server?
Thank you
Yes, seems like it requires a server to be online at all times. But that's how all modern chat applications on smartphones work (Telegram, Whatsapp, Threema, all google chats...). Without a server you would rely on the fact that both smartphones are online at the same time in order to establish a direct connection. This is a huge disadvantage and works against any power-saving features of the mobile OS. Also two parties can hardly communicate if they are always online at different times.
So essentially you need to decide for yourself whether you really want a peer-to-peer or a server-based chat. Just remember that even in case of P2P, you will have to figure out the IP addresses of the other chat clients. And then you'll probably have to use some sort of server, again.
What you need is a P2P chat implementation, you can use WIFI direct for that in Android. Checkout this code: https://github.com/life0fun/wifi-direct-chat
Usually the chat apps need to have a central server to receive the messages and send it to the correct nodes. That code you paste is that kind of implementation.
I have a trouble with my HttpsConnection on android.
First of all, no it is not a duplicate. I try almost all the solutions on SO, like changing the keep-alive option or the timeout ( and some of them indeed optimized a part of my code a little bit ) but it is still 5 to 10 times ( probably more ) slower on android than on iOS.
Sending a request to my server takes several seconds on android while it's almost instant on iOS and from a browser. I am sure that the server is not in cause. But it seems that getting the inputstream is terribly slow!
This line:
in=conn.getInputStream();
is the most delaying one, taking several seconds by itself.
My aim is to get a JSON from my server. My code is supposed to be technically as optimized as possible ( and it can probably help some people with HttpsConnection on the same time ):
protected String getContentUrl(String apiURL)
{
StringBuilder builder = new StringBuilder();
String line=null;
String result="";
HttpsURLConnection conn= null;
InputStream in= null;
try {
URL url;
// get URL content
url = new URL(apiURL);
System.setProperty("http.keepAlive", "false");
trustAllHosts();
conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(DO_NOT_VERIFY);
conn.setRequestMethod("GET");
conn.setRequestProperty(MainActivity.API_TOKEN, MainActivity.ENCRYPTED_TOKEN);
conn.setRequestProperty("Connection", "close");
conn.setConnectTimeout(1000);
in=conn.getInputStream();
// open the stream and put it into BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((line=br.readLine())!= null) {
builder.append(line);
}
result=builder.toString();
//System.out.print(result);
br.close();
} catch (MalformedURLException e) {
result=null;
} catch (IOException e) {
result=null;
} catch (Exception e) {
result=null;
}
finally {
try {
in.close();
}catch(Exception e){}
try {
conn.disconnect();
}catch(Exception e){}
return result;
}
}
However, it keeps taking several seconds.
So I would like to know: is there a way to improve the speed of this API call? The problem is not the server or the JSON parsing but for sure the function above. Thanks a lot.
Confused too much! What is the sole purpose of using BufferReader, InputStream and StringBuffer. Why they should be used and in what kind of a sequence / pattern we should code them. I recently came across a chunk of code while understanding how to send and receive HTTP requests using HttpUrlConnection in android. I tried to search for all these terms and I did not get what I need. In this case, how to use each of them in a sequence or pattern? Any simple example for using all these three in combination would be great. And also kindly what should be all these 3 in layman terms? Thanks
InputStream is used for reading byte based data from the web server (or url) one byte at a time.
BufferReader it is used for reading data from an input stream all by once
StringBuffer A modifiable sequence of characters for use in creating strings, where all accesses are synchronized. This class has mostly been replaced by StringBuilder because this synchronization is rarely useful. This class is mainly used to interact with legacy APIs that expose it. [Did not understand what it means as my official language is not English]
//These two need to be declared outside the try/catch
//so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
//Will contain the raw JSON response as a string.
String forecastJsonStr = null;
try {
//Construct the URL for the OpenWeatherMap query
//Possible parameters are avaiable at OWM's forecast API page, at
//http://openweathermap.org/API#forecast
URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7");
//Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
//Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
//Nothing to do.
forecastJsonStr = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
//Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
//But it does make debugging a *lot* easier if you print out the completed
//buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
//Stream was empty. No point in parsing.
forecastJsonStr = null;
}
forecastJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
//If the code didn't successfully get the weather data, there's no point in attemping
//to parse it.
forecastJsonStr = null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
I am developing an app that logs onto a tomcat server.
I am using a HTTP GET request to do so, and upon successful connection,
the message is displayed via a buffered stream.
The following code, is used to connect.
public String getInternetData() throws Exception {
BufferedReader in = null;
String data = null;
try {
HttpClient client = new DefaultHttpClient();
client.getConnectionManager().getSchemeRegistry().register(getMockedScheme());
URI website = new URI("https://ts.rks.com:8443/kss/login?username=hydm&password=pw1234");
HttpGet request = new HttpGet();
request.setURI(website);
HttpResponse response = client.execute(request);
response.getStatusLine().getStatusCode();
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String l = "";
String nl = System.getProperty("line.separator");
while ((l = in.readLine()) != null) {
sb.append(l + nl);
}
in.close();
data = sb.toString();
return data;
} finally {
if (in != null) {
try {
in.close();
return data;
} catch (Exception e) {
Log.e("GetMethodLogin", e.getMessage());
}
}
}
This is the code that is activated when the user logs in via a login activity.
When I go back to the menu screen and try to run another activity that requires the user
to be logged in, it says that the user is not logged in.
Is the connection being disconnected when the user moves away from the activity or am I not establishing the connection correctly.
There are actually two things you need to change, not just one.
Anything that you need to have persistent across Activities should be done in a Service, not in the code of an Activity.
Second, on recent Android releases, all networking must be done from background threads, rather than the UI thread (there was always a recommendation against UI thread networking, but now it triggers an exception). Just putting the code in a Service does not mean it is in another thread.
So the answer is that you should be doing this using one of the background threading mechanisms, and doing that within a Service.
The connection will not persist when the activity is moved to the background. I cannot tell from your posted code, but I believe you should be using an AsyncTask for this connection. This is coming from my experience pulling HTML source from a link.
This question may answer yours: What to do with AsyncTask in onPause()?