1

I want to make a small change to the Android standard TimePicker class. Specifically, I'm trying to change it so it works in 15 minute increments, rather than 1 minute increments.

This post helped me constrain the range of minute values to {0, 15, 30, 45}, as required in my app. But as I pointed out in a follow up comment, the minute spinner still shows previous minute as current value - 1, and the next minute as current value + 1, which creates a sloppy-feeling user interface.

I looked into the relevant Android source code, and it appears that the changes I would need to make are pretty simple. But when I tried copying the source code into my project I got about a zillion errors relating to the package declaration, where to find Widget, how to resolve R.id variables, etc.

So my question is:

What's the best way to make a small change to a given class from Android source code, and incorporate it into your own project?

In my case, I just need to make a few small changes to TimePicker and NumberPicker, but I'm not sure how to properly set this up in my project.

Thanks for any suggestions.

Community
  • 1
  • 1
gcl1
  • 4,070
  • 11
  • 38
  • 55

2 Answers2

1

But when I tried copying the source code into my project I got about a zillion errors relating to the package declaration

Your source file's directory needs to match the package name. And since you cannot overwrite android.widget.TimePicker, you will either need to move that class to a new package or give it a new name.

where to find Widget

That implies that you copied TimePicker into one of your packages. That is fine, but then you need to add in the appropriate import statements for classes that TimePicker referred to from its original package. Or, you need to keep your (renamed) TimePicker in android.widget, adding this package to your project. This is rudimentary Java.

how to resolve R.id variables

If TimePicker relies upon resources that are not part of the Android SDK, you will need to copy those resources from the AOSP into your project as well.

What's the best way to make a small change to a given class from Android source code, and incorporate it into your own project?

IMHO, that cannot be answered readily in the abstract. Generally speaking, you do the sorts of things that I listed above.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks for your reply. Given your comments, would the following be a doable approach: 1) add the android.widget package to my project, 2) copy TimePicker and NumberPicker classes from Android open source to new classes in my project, 3) rename TimePicker and NumberPicker to something else, and make the small changes I've already identified? – gcl1 Apr 18 '13 at 15:08
  • Also @CommonsWare: if the above approach makes sense, how/where would I obtain android.widget as a package? – gcl1 Apr 18 '13 at 15:27
  • @gcl1: "would the following be a doable approach" -- it is certainly worth trying. "how/where would I obtain android.widget as a package?" -- I guess that I do not understand your question. In Java, a package is signified by a `package` line in the source code, which must match up with the path to the source file. In your case, add `src/android/widget/` and put the code there. Also, be sure to follow the license terms for the code that you are reusing. – CommonsWare Apr 18 '13 at 15:46
0

You are best off subclassing the relevant classes and overriding the methods you would like to change.

In Java, you can do the following in a subclass:

  • The inherited fields can be used directly, just like any other fields.
  • You can declare a field in the subclass with the same name as the one in the superclass, thus hiding it (not recommended).
  • You can declare new fields in the subclass that are not in the superclass.
  • The inherited methods can be used directly as they are.
  • You can write a new instance method in the subclass that has the same signature as the one in the superclass, thus overriding it.
  • You can write a new static method in the subclass that has the same signature as the one in the superclass, thus hiding it.
  • You can declare new methods in the subclass that are not in the superclass.
  • You can write a subclass constructor that invokes the constructor of the superclass, either implicitly or by using the keyword super.

    More info on subclassing in Java

Crake
  • 1,661
  • 1
  • 13
  • 30
  • Thanks for your reply. This seems like a good way to go, but in my case, I would need to change a private variable (mMinuteSpinner) for which there is no direct accessor method. Specifically, I'd need to change an argument of a member function (setOnValueChangedListener()) to use a different version of an anonymous inner class (MyNumberPicker to increment by 15, instead of NumberPicker which increments by 1). Do you think that's all doable using subclassing? – gcl1 Apr 18 '13 at 15:12
  • You could try and use reflection to gain access to the private variable, or you just override whatever method is being called to render the control and use a different variable. I am sure it is possible with subclassing to get what you want, but I am not certain if it will end up being more or less work than modifying the source (and the headaches you are running into associated with that). – Crake Apr 18 '13 at 16:29
  • It turns out the method I need to change is the constructor of the TimePicker class. And the change I need to make is to another class it instantiates. Too bad Google didn't just provide a minutes increment value for the TimePicker, like Apple did for its equivalent in iOS! I don't think this would be very hard for someone who already has their hands in the code. Thanks for your suggestions. – gcl1 Apr 18 '13 at 17:00