If you have access to internet can obtain the current date/time using a Public NTP Time Server.
Since access to the service is a network operation it will have to be done in a thread other than Uithread.
For this case the most appropriate is to use an Intentservice.
Timeservice.java
public class TimeService extends IntentService {
public static final String RESULT_RECEIVER_EXTRA = "result_receiver_extra";
public static final String RESULT_DATA_KEY = "result_data_key";
public static final int SUCCESS_RESULT = 0;
public static final int FAILURE_RESULT = 1;
public static final String FAILURE_MESSAGE_KEY = "failure_message_key";
private final String TIME_SERVER = "time.nist.gov";
private ResultReceiver resultReceiver;
public TimeService() {
super("TimeService");
}
//Método para facilitar o uso do Service
public static void requestTime(@NonNull Context context,
@NonNull ResultReceiver resultReceiver) {
Intent intent = new Intent(context, TimeService.class);
intent.putExtra(RESULT_RECEIVER_EXTRA, resultReceiver);
context.startService(intent);
}
@Override
protected void onHandleIntent(@NonNull Intent intent) {
resultReceiver = intent.getParcelableExtra(RESULT_RECEIVER_EXTRA);
if(resultReceiver == null){
throw new IllegalArgumentException("No ResultReceiver");
}
deliverResultToReceiver(getTime());
}
private TimeResult getTime(){
NTPUDPClient timeClient = new NTPUDPClient();
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getByName(TIME_SERVER);
} catch (UnknownHostException e) {
return new TimeResult(FAILURE_RESULT, -1, e.getMessage());
}
TimeInfo timeInfo = null;
try {
timeInfo = timeClient.getTime(inetAddress);
} catch (IOException e) {
return new TimeResult(FAILURE_RESULT, -1, e.getMessage());
}
long time = timeInfo.getMessage().getTransmitTimeStamp().getTime();
return new TimeResult(SUCCESS_RESULT, time, "");
}
//Usa o ResultReceiver para enviar o resultado
private void deliverResultToReceiver(TimeResult result){
Bundle bundle = new Bundle();
bundle.putString(FAILURE_MESSAGE_KEY, result.failureMessage);
bundle.putLong(RESULT_DATA_KEY, result.time);
resultReceiver.send(result.resultCode, bundle);
}
private class TimeResult{
int resultCode;
String failureMessage;
long time;
protected TimeResult(int resultCode, long time, String failureMessage){
this.resultCode = resultCode;
this.time = time;
this.failureMessage = failureMessage;
}
}
}
The service, to communicate with NTP Time Server, uses the class Ntpudpclient.
It is necessary to indicate this dependency, so add
compile 'commons-net:commons-net:3.3'
in the Builder.Gradle module.
To use Intentservice use the method
public static void requestTime(@NonNull Context context,
@NonNull ResultReceiver resultReceiver)
The service uses the object resultReceiver
to communicate the result.
Example of an Activity to use the service.
Timeactivity.java
public class TimeActivity extends AppCompatActivity {
private TextView tvResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
tvResult = (TextView)findViewById(R.id.tvResult);
}
public void onClickGetTime(View view) {
tvResult.setText("Loading...");
TimeService.requestTime(this, new TimeResultReceiver(new Handler(), this));
}
private static class TimeResultReceiver extends ResultReceiver {
private WeakReference<TimeActivity> activityWeakReference;
public TimeResultReceiver(Handler handler, TimeActivity activity) {
super(handler);
activityWeakReference = new WeakReference<>(activity);
}
@Override
protected void onReceiveResult(int resultCode, @NonNull Bundle resultData) {
TimeActivity activity = activityWeakReference.get();
if (activity != null) {
switch (resultCode)
{
case TimeService.SUCCESS_RESULT:
long result = resultData.getLong(TimeService.RESULT_DATA_KEY);
activity.handleResult(result);
break;
case TimeService.FAILURE_RESULT:
String failureMassage = resultData.getString(TimeService.FAILURE_MESSAGE_KEY);
activity.handleFailure(failureMassage);
break;
default:
throw new IllegalArgumentException("Invalid result code");
}
}
}
}
private void handleFailure(String failureMassage) {
tvResult.setText("Error");
Toast.makeText(this, failureMassage, Toast.LENGTH_SHORT).show();
}
private void handleResult(long result) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date resultDate = new Date(result);
tvResult.setText(simpleDateFormat.format(resultDate));
}
}
activity_time.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btCalculate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get Time"
android:onClick="onClickGetTime"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hora actual: "/>
<TextView
android:id="@+id/tvResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
Notes:
Your application needs GPS on to work?
– ramaral
Yes you do, I have an app similar to taxi apps...
– Mateus Carvalho
Sorry, it wasn’t GPS but internet access.
– ramaral