With resources, there’s built-in support for providing alternatives for different languages, OS versions, screen orientations, etc., as described here. None of that is available with assets. Also, many parts of the API support the use of resource identifiers. Finally, the names of the resources are turned into constant field names that are checked at compile time, so there’s less of an opportunity for mismatches between the code and the resources themselves. None of that applies to assets.
So why have an assets folder at all? If you want to compute the asset you want to use at run time, it’s pretty easy. With resources, you would have to declare a list of all the resource IDs that might be used and compute an index into the the list. (This is kind of awkward and introduces opportunities for error if the set of resources changes in the development cycle.) (EDIT: you can retrieve a resource ID by name using
getIdentifier, but this loses the benefits of compile-time checking.) Assets can also be organized into a folder hierarchy, which is not supported by resources. It’s a different way of managing data. Although resources cover most of the cases, assets have their occasional use.
One other difference: resources defined in a library project are automatically imported to application projects that depend on the library. For assets, that doesn’t happen; asset files must be present in the assets directory of the application project(s). [EDIT: With Android’s new Gradle-based build system (used with Android Studio), this is no longer true. Asset directories for library projects are packaged into the .aar files, so assets defined in library projects are merged into application projects (so they do not have to be present in the application’s
/assets directory if they are in a referenced library).]
EDIT: Yet another difference arises if you want to package a custom font with your app. There are API calls to create a
Typeface from a font file stored in the file system or in your app’s
assets/ directory. But there is no API to create a
Typeface from a font file stored in the
res/ directory (or from an
InputStream, which would allow use of the
res/ directory). [NOTE: With Android O (now available in alpha preview) you will be able to include custom fonts as resources. See the description here of this long-overdue feature. However, as long as your minimum API level is 25 or less, you’ll have to stick with packaging custom fonts as assets rather than as resources.]