Let me try to explain.
Covariance and contravariance aren't about whether you can store a Dog instance in an Array<Animal> (given that Dog is a subclass of Animal). Like you said, that should work just fine.
Imagine you have a generic class, Foo<T>. We know that Dog is a subclass of Animal, so you can use a Dog anywhere you can use an Animal. The question is, can you use a Foo<Dog> anywhere you can use a Foo<Animal>? The answer is, it depends.
If Foo is covariant, the answer is yes. If Dog is a subclass of Animal, then Foo<Dog> should be considered a subclass of Foo<Animal>.
If Foo is contravariant, the answer is no, and it's the opposite: a Foo<Animal> should be considered a subclass of Foo<Dog>.
If Foo is invariant, the answer is no, and Foo<Animal> and Foo<Dog> have no subclass/superclass relation to each other.
Which case is true depends on what you want Foo to do, and is something the creator of the class decides. For example, if Foo is a class representing an immutable list, then Foo can be declared as covariant. (So, you should be able to use a List<Dog> anywhere you can use a List<Animal>.) However, is Foo is a class representing a mutable list, and you declare it as covariant, you can get yourself into trouble. Here is a Stack Overflow answer where someone explains why the (mutable) List<T> in Java isn't covariant, and what sort of problem you could get into if you made it covariant: http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p/2745301#2745301.
I hope this makes things a little clearer.