My biggest doubt about this structure is: How would I return all this data to my Android app. Is it correct to return a JSON with the notification unpopulated (only ID's), and the Android app would use the ID's and query the API to build the notification. I mean, the client would make a call to: /getUser/:id to get the username, then /getActivity/:id to get the activity details, you get the point... Wouldn't that be to much calls just for a notification?
That's why your documents should have all the information instead of references to different collections. Even if it means duplicating information. It doesn't matter. If the original "feed" is edited, then a new "Message" is created (or the older one is updated) and "published".
MongoDB "supports" joins through lookups and newer versions of MongoDB might support SQL but whether you can take advantage of these features will depend on the specific programming language drivers and the specific MongoDB version! Something I have learnt the hard way. Upgrading the DB version was no longer as easy as promoting to the next version. It takes a lot of tests to ensure that the new version doesn't cause breaking changes and the new drivers either. The features you are coupled with must behave exactly the same way and the query operators have the very same contract and format. That's something you don't have to care about with most of the RDBMS. But with MongoDB, you must.
For example, MongoDB supports different Aggregation operations, but it takes having the latest java driver to be able to use'em all programmatically. If you design your documents in such a way your queries depend purely on core features it's unlikely changing the MongoDB version will have any impact on your source code or dependencies.
I can't tell you what specific model you should return to the Android client, but in any case, regardless of how data is persisted, you can return a projection with the bare minimum information to make the message readable. So, use lookup and projections to compose specific MongoDB response models and map them to DTOs.
If you have to fetch more information from other sources, do it on the server-side and complete the DTO you obtained in the first place. That's the whole point of DTOs.
If you return a snapshot of the message, the user has something to read and enough information to decide whether it is worth reading the whole message (which will trigger a second request) or just ignore it.
What's the best way for my client to get the latest activity? Just query the database for the latest inserted data that matches the criteria?
No silver bullets or shortcuts here. It's an architectural decision you should make based on your needs. You can re-invent the wheel with MongoDB and your programming language or you can use existing solutions. Essentially you will look for solutions supporting pub-sub patterns. Note that, you don't have to code this in the same backend. You can promote this feature and make it a standalone service, written (or not) in a different language. Whatever takes less effort to maintain.