Wikimedia Apps/Team/Android/App hacking

The Wikipedia Android app is completely open-source and welcomes contributions from all. Our code repo is at github.com/wikimedia/apps-android-wikipedia.

We welcome volunteer contributions!
Follow the steps below to get started, and feel free to ping any member of the WMF Android dev team (dbrant, cooltey, sharan) on  for assistance.

Making good pull requests
Ideally, pull requests from volunteers should be:


 * Small and concise: Your pull request should fix a single specific issue, or implement a single specific feature. Be very clear about what your pull request does, and make sure the code is clean and readable.
 * Testable: Whenever possible, include a unit test or two in your pull request.

Please avoid making these types of contributions:


 * Complete overhauls of our code: A pull request that converts our entire code base to Kotlin might be very impressive in its size, but it's completely unusable to us because of the amount of reviewing, testing, and adjusting that we would need to do to accept it. Huge fundamental changes to our code are done gradually, and are decided by us internally as a team.
 * Adopt shiny new library X throughout the app: Similarly, adopting a new library (especially one that impacts our code in a fundamental way) is a decision that we make internally as a team. Please ask us first before undertaking such a task.

Open bugs and feature requests
Work items are tracked on our work board. First time app contributors are encouraged to consider a good first task. Unassigned tasks in the "Bug Backlog", "Tech Debt Backlog", and "Product Backlog" columns are generally suitable for development and roughly organized by descending priority. (Please do not work on tasks in other columns like "Open Questions" and "Needs Triage".)

Set up a development environment

 * Create a GitHub account.
 * Add your SSH key to GitHub.
 * Download and install Android Studio: https://developer.android.com/studio

Download the project source
If you plan on contributing to the project, you should create a fork of the repository into your own account, and checkout the fork. Otherwise you can simply checkout the code of our repository itself:

With SSH credentials (requires GitHub account):

Or anonymously:

Checkout and/or update any submodules within the project:

Open in Android Studio
Open Android Studio, select "Open an existing Android Studio Project" from the main window, and select the repository folder from the file browser.

Important: If you are prompted about upgrades to components (e.g., Gradle or the Android Gradle plugin) during the initial build, please click "Don't remind me again for this project." We update these components in dedicated patches after a thorough review of the release notes, but they have a way of showing up in unrelated patches if automatic IDE prompting is enabled.

Make changes and submit for review via GitHub
If the changes are not associated with any task in Phabricator, you can create a branch with a meaningful name of it.

Make and commit your changes, and provide a commit message describing your changes. (Please ensure that the commit message includes line breaks for lines running over 75 characters.) If your work is associated with a specific task in Phabricator, please include, as the last line of the commit message, the following line:

(where xxxxxx represents the number of the Phabricator task, e.g., T149500).

After creating your commit, if this is your first of submitting the changes to the branch, you may need to set the upstream to it. Once the command is done above, you can simply use the following command when you are in the branch you've been working on. You'll most likely receive requests to update and resubmit the patch. (It happens to all of us!) Make these changes locally and use   to submit your update changes, and make sure the commits are in the same branch.

After submitting a new branch to GitHub, you can create a Pull Request for other developers to review the changes. For more information, see Creating a pull request

Tip: To avoid CI test failures, it's a good idea to run checkstyle and the unit test suite (  or  ) from the project root before pushing to GitHub.

Automated Tests
The codebase supports two kinds of tests:
 * 1) JVM JUnit (preferred, off device, fast, less flaky)
 * 2) Android instrumentation (on device)

Command line usage

 * JVM JUnit
 * Android instrumentation
 * Both JVM JUnit and Android instrumentation (including screenshot tests)
 * Both JVM JUnit and Android instrumentation (including screenshot tests)
 * Both JVM JUnit and Android instrumentation (including screenshot tests)

Tips

 * When running, add the   flag to run the Android instrumentation tests even if the JVM JUnit tests failed.

Android Studio setup
Both kinds of tests are supported in Android Studio. You may toggle between them by changing the Test Artifact from View -> Tool Windows -> Build Variants. "Unit Tests" are JVM JUnit tests and "Android Instrumentation Tests" are what it says. A run configuration must be made to prior to executing the tests.

Help make it better!
Pick a task from Phabricator: Testing:
 * good first tasks / All tasks.
 * Alpha release (old Alpha release build server)
 * Beta release
 * Production release

See pending/recent code reviews:
 * Wikipedia Android app
 * Java MediaWiki-API
 * MediaWiki MobileApp extension

WebView debugging in Chrome
Wikipedia for Android makes extensive use of WebViews. To debug WebView activity, navigate Google Chrome to chrome://inspect/#devices, then click on the topmost “inspect” link under “WebView in org.wikipedia.” From there you can debug the WebView like any other web site in Chrome.

Optimizing Gradle builds
The Gradle build system requires a notoriously large amount of system resources, but there are ways of speeding it up and making sure it works consistently. Add the following lines to your  file:

org.gradle.daemon=true org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx2048M

Useful Gradle commands
If you prefer command line use the wrapper script in the root of the repo: ./gradlew

To run a clean debug build: ./gradlew -q clean assembleDevDebug

You can skip the clean part usually, which makes it much faster (from 1m:05s to 7s on my box): ./gradlew -q assembleDevDebug

To install build on device/emulator: ./gradlew -q installDevDebug

To see ProGuard output: ./gradlew clean --info proguardDevRelease

To run checkstyle: ./gradlew checkstyle

To run Lint: ./gradlew lintDevDebug

To refresh dependencies (usually not needed): ./gradlew --refresh-dependencies

To list dependencies: ./gradlew app:dependencies --configuration compile

Developer Settings
When using the dev build variant the developer settings are enabled automatically. For other flavors you could tap 7 times on the Wikipedia globe on the About page. Once enabled, you can open the developer settings by accessing the app settings, then tap on the icon on the right in the top toolbar.

Working with Vagrant and the Content Service

 * To work with a local Vagrant instance, change the mediaWikiBaseUri developer setting and optionally disable mediaWikiBaseUriSupportsLangCode.
 * To work with a local RESTBase instance, update RESTBaseUriFormat and optionally enable useRestbase_setManually.
 * mediaWikiBaseUriSupportsLangCode controls whether the wiki language of mediaWikiBaseUri is prefixed.
 * mediaWikiBaseUri and mediaWikiBaseUriSupportsLangCode are the second argument of RESTBaseUriFormat.
 * useRestbase_setManually and useRestbase can affect whether a MediaWiki or RESTBase client is used internally. When a MediaWiki client is forced, RESTBaseUriFormat is unused.
 * The Wiktionary domain is currently hardcoded. Ex: http://localhost:6927/en.wiktionary.org/v1/page/definition/dog
 * It is recommend to fully terminate the app process after changing any of these settings.

Beta cluster config
Ex:
 * https://en.wikipedia.beta.wmflabs.org/api/rest_v1/feed/featured/2016/06/01
 * https://zh.wikipedia.beta.wmflabs.org/api/rest_v1/page/random/title

RESTBaseUriFormat (default): %1$s://%2$s/api/rest_v1/ mediaWikiBaseUriSupportsLangCode (default): enabled mediaWikiBaseUri (nondefault): https://wikipedia.beta.wmflabs.org

Local MediaWiki with production English Content Service config
Ex:
 * http://localhost:8080/w/api.php?action=query&format=json&titles=Main_Page&continue=&prop=pageimages&piprop=thumbnail&pithumbsize=320&pilimit=1

RESTBaseUriFormat (nondefault): %1$s://en.wikipedia.org/api/rest_v1/ mediaWikiBaseUriSupportsLangCode (nondefault): disabled mediaWikiBaseUri (nondefault): http://localhost:8080

Auth manager config
RESTBaseUriFormat (default): %1$s://%2$s/api/rest_v1/ mediaWikiBaseUriSupportsLangCode (nondefault): disabled mediaWikiBaseUri (nondefault): http://authmanager.wmflabs.org

Local Content Service config (broken)
Ex:
 * http://localhost:6927/en.wikipedia.org/v1/page/most-read/2015/12/01
 * http://192.168.1.10:6927/zh.wikipedia.org/v1/page/mobile-sections/%E4%B8%AD%E5%9C%8B

useRestbase_setManually (nondefault): enabled useRestbase (default): enabled RESTBaseUriFormat (nondefault): http://localhost:6927/%2$s/v1/ mediaWikiBaseUriSupportsLangCode (default): enabled mediaWikiBaseUri (default): https://wikipedia.org

This doesn't quite work at moment. The app attempts to use a RESTBase feed/ endpoint when page/ is needed for the Content Service.

Local Vagrant with local Content Service config (broken)

 * http://192.168.1.11:6927/192.168.1.11:8080/v1/feed/featured/2016/10/11

useRestbase_setManually (nondefault): enabled useRestbase (default): enabled RESTBaseUriFormat (nondefault): http://localhost:6927/%2$s/v1/ mediaWikiBaseUriSupportsLangCode (nondefault): disabled mediaWikiBaseUri (default): http://localhost:8080

This is currently broken for same reason the local Content Service config is.

Setup
Note: the lxml Python module seems to have system package dependencies on Debian and Ubuntu. If you're missing headers, try.

Troubleshooting Script Setup
On OS X a few of us ran into the issue that `libxml` couldn't get compiled. Running the following command helped: xcode-select --install If this still doesn't work, you might also want to try: pip install sh jinja2 unicodecsv

This will produce output files under  which will be included in the apk file.

Would like to try  with a local   repo? Please refer the and then follow the steps above.

Remote configuration
On startup, the app attempts to update its configuration by checking a JSON config file updated as part of the MobileApp extension. This remote configuration file is typically used for things like managing EventLogging sampling rates or rolling out new features incrementally.

On Wikimedia production wikis, as well as on the Beta Cluster or a local MediaWiki environment (such as MediaWiki-Vagrant) with the MobileApp extension, the file is located at:

See T162164 for details on the treatment of static files in the Wikimedia production environment.

Purging the cached configuration (note: requires production shell access)
After a configuration update is deployed, making it available in production before the old version naturally expires out of cache will require a purge.

To do so:

ssh tin echo " https://meta.wikimedia.org/w/extensions/MobileApp/config/android.json " | mwscript purgeList.php --wiki=aawiki

String resource translations
The app's string resources are translated by the volunteer community at Translatewiki.net. See Translation of app string resources (and in particular the section TWN sync for Android) for details.