2

I'm developing an Android application for in-house of a certain company, and it needs to log the working time of employees. Therefore, the work with system time is crucial. My application badly needs to know when the user changes the system time. Big deal, you say, see this: Is there a way to detect when the user has changed the clock time on their device?

The problem is that the user may circumvent that solution by doing Force Stop of the application prior to changing the time. The application then won't receive system notification, which is brilliantly described here: https://stackoverflow.com/a/19856367/1309803

I don't mind checking that upon the next launch of the application, but how can I possibly know if the user has changed the time? I'm aware about SystemClock.elapsedRealtime(). I could figure time shift based on delta of those values provided that the user hasn't reboot the device, but this is what I'm unsure of. My application is subscribed to BOOT_COMPLETED event, but that one won't be received either while the application is in stopped state.

And, to cap it all, employees of that company are supposed to work in condition of having no network access, so I can't rely on Web servers. So is there any other possible approach?

Community
  • 1
  • 1
mbakulin
  • 181
  • 1
  • 9
  • have you tryed to use a Service in conjunction with the START_STICKY in onStartCommand() to achive an "unkillable" enviroment for the timeChanging observations? – Paul Reznik Jun 05 '15 at 12:42
  • @Videndeta Could you kindly expand your suggestion a little? I don't imagine how the service can help against Force Stop scenario. – mbakulin Jun 05 '15 at 13:40
  • a service does run even after the application has been closed. You can also forceclose the Service through the TaskManager of course, but with the START_STICKY attribute, the service will be recreated again. – Paul Reznik Jun 05 '15 at 14:24
  • @Videndeta My problem has exactly to do with force close through the task manager, otherwise Broadcast Receivers would remain capable to receive intents. In this (force close) case the START_STICKY doesn't seem to be relevant (http://stackoverflow.com/a/9441795/1309803). But, even if it did recreate the service, how could I know if the system time was or wasn't changed while it was out? – mbakulin Jun 10 '15 at 07:48
  • Possible duplicate of [Get actual time from internet ?](https://stackoverflow.com/questions/36997161/get-actual-time-from-internet) – Ole V.V. Jul 16 '19 at 11:56

1 Answers1

1

Getting the time from the third-party servers is not reliable most of the times and some of them are paid services.

If you want to get the exact time and check with the phone whether it is correct or not, irrespective of the proper way, you can use the following simple trick to get the actual time.

private class GetActualTime extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... urls) {
            try {
                HttpURLConnection urlConnection = null;
                StringBuilder result = new StringBuilder();
                try {
                    URL url = new URL(urls[0]);
                    urlConnection = (HttpURLConnection) url.openConnection();
                    int code = urlConnection.getResponseCode();
                    if (code == 200) {
                        InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
                        String line = "";
                        while ((line = bufferedReader.readLine()) != null)
                        result.append(line);
                        in.close();
                    }
                        else {
                        return "error on fetching";
                    }
                    return result.toString();
                } catch (MalformedURLException e) {
                    return "malformed URL";
                } catch (IOException e) {
                   return "io exception";
                } finally {
                    if (urlConnection != null) {urlConnection.disconnect();
                    }
                }
            } catch (Exception e) { return "null"; }
        }

        @Override
        protected void onPostExecute(String time) {
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat mdformat = new SimpleDateFormat("h:mm");
            String times =  mdformat.format(calendar.getTime());
            try {
                String areatime = time.substring(time.indexOf(String.valueOf(times)), time.indexOf(String.valueOf(times)) + 5).trim(); 
                        Toast.makeText(this, "The actual time is " + areatime, Toast.LENGTH_SHORT).show();

            }
            catch(IndexOutOfBoundsException e){
                        Toast.makeText(this, "Mobile time is not same as Internet time", Toast.LENGTH_SHORT).show();
                }
            }


        }

    }

Call the class in the onCreate();

new GetActualTime().execute("https://www.google.com/search?q=time");

So this is actually getting the time from Google. This works pretty awesomely in my projects. In order to check whether the system time is wrong, you can use this trick. Instead of depending on the time servers, you can trust Google.

As it is more sensitive in checking, even a minute ahead or lag will catch the exception. You can customise the code if you want to handle that.

Pradeep
  • 798
  • 1
  • 7
  • 18