Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Future Timestamp Error #1

Open
Ch-Tima opened this issue Dec 28, 2024 · 2 comments
Open

Future Timestamp Error #1

Ch-Tima opened this issue Dec 28, 2024 · 2 comments

Comments

@Ch-Tima
Copy link
Owner

Ch-Tima commented Dec 28, 2024

Error:

      Fatal Exception: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
   at java.util.ArrayList.get(ArrayList.java:437)
   at com.chtima.currencyconverter.MainActivity$3.onResponse(MainActivity.java:129)
   at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$retrofit2-DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
   at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1$$ExternalSyntheticLambda0.run(:6)
   at android.os.Handler.handleCallback(Handler.java:938)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:223)
   at android.app.ActivityThread.main(ActivityThread.java:7680)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:423)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Current real Date & Time: 25.12.2024. However, the user can change the Date & Time on their device, for example, to 26.12.2025.
Request to API: https://api.privatbank.ua/p24api/exchange_rates?date=26.12.2025

{
  "date": "26.12.2024",
  "bank": "PB",
  "baseCurrency": 980,
  "baseCurrencyLit": "UAH",
  "exchangeRate": [] <<< here problem!
}
private void loadDataFromAPI(){
        private24Service = retrofit.create(Private24Service.class);

        var dateFormat = new SimpleDateFormat("dd.MM.yyyy");
        var dateNow = dateFormat.format(Calendar.getInstance().getTime());

        private24Service.GetCurrencyRoot(dateNow).enqueue(new Callback<CurrencyRoot>() {
            @Override
            public void onResponse(Call<CurrencyRoot> call, Response<CurrencyRoot> response) {
                if(response.code() == 200 && response.body() != null && response.body().getExchangeRate() != null){
                    CurrencyRoot root = response.body();
                    // BEGIN_LINE_129
                    UserTempData tempData = new UserTempData(
                            root.getExchangeRate().get(0), 
                            root.getExchangeRate().get(1)
                    );
                    // END_LINE_129
                } else {...}
            }

            @Override
            public void onFailure(Call<CurrencyRoot> call, Throwable t) {...}
        });
    }
@Ch-Tima
Copy link
Owner Author

Ch-Tima commented Dec 29, 2024

Better Solution to the Bug: Using the Network Time Protocol (NTP)

The best approach to solve this bug would be to request the "Network Time Protocol" (NTP). However, making an NTP request is a bit challenging. Instead, I found the Play Services Time API by Google, which provides an easier way to get accurate time.

Thanks to TrustedTime, we can obtain the real time from Google Services even "without internet" (though not always, I suppose). This solution seems much more convenient than creating an NTP request or querying an external API.

Here's the updated version of my code to fix the issue:

class MainActivity 
//...
    protected void onCreate(Bundle savedInstanceState) {
        //...code...

        Task<TrustedTimeClient> initializeTrustedTimeClientTask = 
                TrustedTime.createClient(this); <<<< This fixed all
        SharedPreferences sp = SharedPreferencesKeys.getSharedPreferences(this);

        retrofit = new Retrofit.Builder()
                .baseUrl(URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        initializeTrustedTimeClientTask.addOnCompleteListener(task -> {
            var dateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
            dateFormat.setTimeZone(TimeZone.getTimeZone("UTC+2"));

            if(task.isSuccessful()){
                isTrueTime = true;
                Long tms = task.getResult().computeCurrentUnixEpochMillis();
                trueTimeNow = dateFormat.format(new Date(tms));//1730001052195L
                //...code...
            }else {
                //true - the mistake was already there
                if(!sp.getBoolean(SharedPreferencesKeys.ConstKeys.TRUE_TIME_FAIL, false)){
                    //show warning
                }
                isTrueTime = false;
                trueTimeNow = dateFormat.format(new Date(System.currentTimeMillis()));
            }

            CurrencyRoot data = loadCurrenciesFromLocalStorage();
            UserTempData user = loadUserDataFromLocalStorage();

            if(data != null && (user == null ||
                    user.getLastFirstCurrency() == null ||
                    user.getLastSecondCurrency() == null)){
                user = new UserTempData(data.getExchangeRate().get(0), data.getExchangeRate().get(1));
            }

            if(data == null){//first start
                loadDataFromAPI();
            }else if(!data.getDate().equals(trueTimeNow)){//just old data
                this.userTempData = user;
                this.currencyRoot = data;
                isOldData = true;
                loadDataFromAPI();
            }else {//data is exists and new ones
                openMainFragment(data, user);
            }

        });

    }

//...

@Ch-Tima

@Ch-Tima
Copy link
Owner Author

Ch-Tima commented Dec 29, 2024

Currently, this bug has only been fixed in the Play Store version of the app.
The new version 1.4 will be available soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant