0

I read about the problem but I can't find where is my mistake. I have dates in my Datebase and when I retrieve them and try to compare them with the current date this error comes in the logcat:

E/AndroidRuntime: FATAL EXCEPTION: main
       Process: com.example.hpdemon.diploma, PID: 9879
       java.lang.RuntimeException: Unable to start receiver com.example.hpdemon.diploma.BroadcastManager: java.lang.IllegalArgumentException: Bad class: class java.lang.String
           at android.app.ActivityThread.handleReceiver(ActivityThread.java:2417)
           at android.app.ActivityThread.access$1700(ActivityThread.java:138)
           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1275)
           at android.os.Handler.dispatchMessage(Handler.java:102)
           at android.os.Looper.loop(Looper.java:136)
           at android.app.ActivityThread.main(ActivityThread.java:5034)
           at java.lang.reflect.Method.invokeNative(Native Method)
           at java.lang.reflect.Method.invoke(Method.java:515)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:731)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
           at dalvik.system.NativeStart.main(Native Method)
        Caused by: java.lang.IllegalArgumentException: Bad class: class java.lang.String
           at java.text.DateFormat.format(DateFormat.java:296)
           at java.text.Format.format(Format.java:93)
           at com.example.hpdemon.diploma.BroadcastManager.onReceive(BroadcastManager.java:51)
           at android.app.ActivityThread.handleReceiver(ActivityThread.java:2410)
           at android.app.ActivityThread.access$1700(ActivityThread.java:138) 
           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1275) 
           at android.os.Handler.dispatchMessage(Handler.java:102) 
           at android.os.Looper.loop(Looper.java:136) 
           at android.app.ActivityThread.main(ActivityThread.java:5034) 
           at java.lang.reflect.Method.invokeNative(Native Method) 

The error comes on this line deadline = new Date(deadline.getTime() - 604800000L); My code is:

        Users_Database db = new Users_Database(context);
        String currentUsrname = PreferenceManager.getDefaultSharedPreferences(context).getString("USRNFORBROADCAST", "NothingFound");
        List<String> dates=db.getAllDates(db.findID(currentUsrname));
        String dateIns = "";
        String dateVin = "";
        String dateTax = "";
        // int tyres;
        dateIns=(dates.get(0));
        dateVin=(dates.get(1));
        dateTax=(dates.get(2));
        dateIns = dateIns.replaceAll("\n", "");

        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Calendar c = Calendar.getInstance();//текуща дата
        Date todayDate = c.getTime();
        Date deadline=c.getTime();

        try {
            todayDate = sdf.parse(sdf.format(todayDate.getTime()));
            deadline = sdf.parse(sdf.format(dateIns));
            deadline = new Date(deadline.getTime() - 604800000L);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (todayDate.before(deadline) /*&& hour.equals(yourHour)*/) {
            Intent it = new Intent(context, BootServices.class);
            createNotification(context, it, "I Love My Car", "Краен срок!", "Изтичащ преглед");
            context.startService(it);
        }
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Could you post the stacktrace please? – Johannes Kuhn May 19 '18 at 12:25
  • 1
    it is beacuse it expect date or time and you ae passing the String – Masoom Badi May 19 '18 at 12:30
  • @Sam I can't understand where I'm wrong – strelecaaaa May 19 '18 at 12:36
  • error at parse function. – Abhay Koradiya May 19 '18 at 12:42
  • 1
    have a look here https://stackoverflow.com/questions/24041513/java-lang-illegalargumentexception-bad-class-class-java-util-gregoriancalendar/24041714 – Masoom Badi May 19 '18 at 12:52
  • The issue is here (I think): `sdf.format(dateIns)`. You are trying to format something that is already a string. It doesn’t make sense to do, and a `SimpleDateFormat` cannot do it. Therefore it throws the exception. You would have preferred a compile time error message, but since `format` is declared to accept `Object`, you don’t get that. – Ole V.V. May 19 '18 at 17:42
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends, and adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. May 19 '18 at 17:44
  • @OleV.V. Thank you! The problem was sdf.format(dateIns). Because dateIns was a String, after I changed it to Date it works! – strelecaaaa May 19 '18 at 18:48
  • Great that you solved it. And great that you want to share the solution. Please do that in an answer, not by modifying the question. It all makes better sense that way. You may also accept your own answer (after a quarantine period) so that it will be clear for all that a solution has been found. – Ole V.V. May 19 '18 at 20:21

2 Answers2

1

You do not provide enough info for a precise Answer. So here are some pointers.

You are using terrible old date-time classes that were supplanted years ago by the java.time classes.

  • Instant replaced Date
  • ZonedDateTime replaced Calendar
  • DateTimeFormatter replaced SimpleDateFormat

If you must inter-operate with old code not yet updated for java.time, you can convert back and forth by calling new conversion methods added to the old classes.

You are using dumb strings where you should be using smart objects. As of JDBC 4.2, you can directly exchange java.time objects with your database.

Instant instant = myResultSet.getObject( … , Instant.class ) ;

An Instant is always in UTC. To get a date, you must specify a time zone. For any given moment, the date varies around the globe by zone.

ZoneId z = ZoneId.of( "America/Montreal" ) ; 
ZonedDateTime zdt = instant.atZone( z ) ;

Extract a date-only value, apparently your goal.

LocalDate ld = zdt.toLocalDate() ;

Compare by calling isBefore and isAfter.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

java.time

It’s not perfectly clear from the question, but I think you were trying to do something like the following:

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");

    List<String> dates = Arrays.asList("31/05/2018", "19/06/2018", "01/07/2018");
    String dateIns = dates.get(0);
    dateIns = dateIns.replaceAll("\n", "");

    LocalDate todayDate = LocalDate.now(ZoneId.of("Pacific/Rarotonga"));
    LocalDate deadline = LocalDate.parse(dateIns, dateFormatter).minusWeeks(1);
    if (todayDate.isBefore(deadline)) {
        System.out.println("I Love My Car. Краен срок! Изтичащ преглед.");
    }

Running this snippet just now, since 19th May is strictly before 24th May, it printed

I Love My Car. Краен срок! Изтичащ преглед.

Please substitute your desired time zone if it didn’t happen to be Pacific/Rarotonga.

I am using and recommending java.time, the modern Java date and time API. A LocalDate is a date without time of day and seems just right for your needs. And the entire java.time is so much nicer to work with than Date and SimpleDateFormat, which are long outdated, and SimpleDateFormat in particular notoriously troublesome.

If you are using at least Java 8 or Android API level 26 or higher, you should make sure you’ve got a JDBC 4.2 compliant driver and then retrieve LocalDate objects rather than strings from your database. In this way you are free from any parsing of the strings in your code, it is not only easier, it is also less error-prone.

What went wrong in your code?

I believe the issue is in this line:

    deadline = sdf.parse(sdf.format(dateIns));

Here dateIns is a String. It doesn’t make sense to format something that is already a string, and SimpleDateFormat cannot do that and therefore throws the exception you got. You would have preferred and maybe expected a compile-time error message when passing the wrong type to the format method. SimpleDateFormat inherits a format(Date) method from DateFormat but also a format(Object) method from Format. So with the String the latter is called, and the compiler has no way of telling that anything is wrong.

Question: Can I use java.time on Android?

Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161