There are two ways to deploy OneBusAway Android in your city:
- Join the OneBusAway multi-region project - The easiest way to get started - simply set up your own OneBusAway server with your own transit data, and get added to all the OneBusAway apps! See this page for details.
- Deploy a rebranded version of OneBusAway Android as your own app on Google Play - Requires a bit more maintenance, but it allows you to set up your own app on Google Play based on the OneBusAway Android source code, and with your brand name and colors. This page discusses this option in detail.
We use Gradle build flavors to enable a number of different build variants of OneBusAway Android.
We have one Gradle "platform" flavor dimension:
- google = Normal Google Play release
...and several Gradle "brand" flavor dimensions:
- oba = Original OneBusAway brand
- agencyX = A sample rebranded version of OneBusAway for a fictitious "Agency X"
- agencyY = A sample rebranded version of OneBusAway for a fictitious "Agency Y"
- kiedybus = KiedyBus, a Polish transit app
Here's where you can download the apps for each of these brands on Google Play:
And here are screenshots for these 3 brands:
Each brand is deployed as an independent app on Google Play (using the google platform flavor).
To build a variant, you need to combine the platform flavor with the brand flavor. For example, the original OneBusAway brand for the Google platform can be built with:
gradlew installObaGoogleDebug
Brand flavors are defined in separate files in the onebusaway-android/flavors/ directory. This keeps the main build.gradle clean and makes it easy to add new brands.
First, we recommend that you review the sample brands (agencyX, agencyY, kiedybus) to see how brands are implemented.
Here are the high-level steps to add a new brand, for a new brand name newBrandName:
- Create a new flavor configuration file
onebusaway-android/flavors/newBrandName.gradle - Create a new folder
src/newBrandName/reswith the appropriate resource files (or copy from one of the samples) - Edit resource files in
src/newBrandName/ressubfolders with your brand information - Add your own launcher icons for the
res/mipmap-*folders - Configure Google Maps API key for your package name
- Configure Firebase for analytics and crash reporting (optional but recommended)
Copy an existing flavor file as a template:
cp onebusaway-android/flavors/agencyX.gradle onebusaway-android/flavors/newBrandName.gradleEdit the file and update:
android.productFlavors {
newBrandName {
dimension "brand"
applicationId "com.newbrandname.android" // Your unique package name
manifestPlaceholders = [databaseAuthority: applicationId.toString() + '.provider']
buildConfigField "int", "ARRIVAL_INFO_STYLE", "0"
buildConfigField "boolean", "USE_FIXED_REGION", "false" // or "true" for single-region
// ... other configuration options
}
}See flavors/README.md for the complete list of configuration options.
Create minimal resources in src/newBrandName/res/:
src/newBrandName/
└── res/
├── values/
│ ├── strings.xml # App name (required)
│ ├── colors.xml # Theme colors (required)
│ └── do_not_translate.xml # API keys, URLs (required)
└── mipmap-*/
│ ├── ic_launcher.png # App icon (all densities)
│ └── ic_launcher_round.png
└── values-night/
└── colors.xml # Dark Theme colors (required)
Thanks to the placeholder system, you typically only need to override app_name:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">New Brand Name</string>
</resources>All other branded strings use %1$s placeholders that automatically substitute your app name.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="brand_color">#YOUR_PRIMARY_COLOR</color>
<color name="brand_color_dark">#YOUR_DARK_COLOR</color>
<color name="theme_muted">#YOUR_MUTED_COLOR</color>
<color name="theme_accent">#YOUR_ACCENT_COLOR</color>
<color name="tutorial_background">#dfYOUR_PRIMARY</color>
<color name="ic_launcher_background">#YOUR_PRIMARY_COLOR</color>
<!-- Keep on-time color green even if your theme isn't green -->
<color name="stop_info_ontime">#4CAF50</color>
</resources>To override material 3 colors, please checkout the theme builder.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="apiv2_key">YOUR_GOOGLE_MAPS_API_KEY</string>
<!-- Only if using custom regions API: -->
<string name="regions_api_url">https://your-domain.com/regions.json</string>
</resources>Use one of these tools to generate icons for all densities:
- Android Asset Studio
- Image Asset Studio in Android Studio
Required sizes:
- mdpi: 48x48
- hdpi: 72x72
- xhdpi: 96x96
- xxhdpi: 144x144
- xxxhdpi: 192x192
Google Maps requires an API key that is restricted to your app's package name.
- Go to the Google Cloud Console
- Create a new project or select an existing one
- Enable the Maps SDK for Android API
- Go to Credentials and create an API key
- Restrict the key:
- Click on the API key to edit it
- Under "Application restrictions", select Android apps
- Add your package name (e.g.,
com.newbrandname.android) - Add your app's SHA-1 fingerprint:
# For debug builds: keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android # For release builds, use your release keystore
- Copy the API key to
src/newBrandName/res/values/do_not_translate.xml
Important: You need separate SHA-1 fingerprints for debug and release builds. For production, add both fingerprints to your API key restrictions.
See Google's documentation for more details.
Firebase provides analytics and crash reporting. To set up Firebase for your brand:
- Go to the Firebase Console
- Create a new project or select an existing one
- Click Add app and select Android
- Enter your package name (e.g.,
com.newbrandname.android) - Download the
google-services.jsonfile - Important: Don't replace the existing
google-services.json. Instead, add your app's client configuration to the existing file.
Open onebusaway-android/google-services.json and add your app's client entry to the client array:
{
"project_info": { ... },
"client": [
// ... existing entries ...
{
"client_info": {
"mobilesdk_app_id": "1:YOUR_PROJECT_NUMBER:android:YOUR_APP_ID",
"android_client_info": {
"package_name": "com.newbrandname.android"
}
},
"oauth_client": [
{
"client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "YOUR_FIREBASE_API_KEY"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
]
}You can find these values in the google-services.json file you downloaded from Firebase Console.
Note: If you don't configure Firebase, the app will still build and run, but you won't have analytics or crash reporting for your brand.
./gradlew assembleNewBrandNameGoogleDebug
./gradlew installNewBrandNameGoogleDebugThe app uses a placeholder system for branded strings, which significantly reduces the work needed to support multiple languages in your rebranded app.
How it works: Strings that mention the app name use %1$s as a placeholder, which is automatically replaced with your app_name at runtime. For example:
<!-- In src/main/res/values/strings.xml -->
<string name="tutorial_welcome_title">Welcome to %1$s!</string>
<string name="bad_gateway_error">%1$s\'s servers are overloaded. Please try again.</string>What this means for you: You only need to override app_name in each language your brand supports. All other branded strings will automatically use your app name.
<!-- src/newBrandName/res/values/strings.xml -->
<resources>
<string name="app_name">New Brand Name</string>
</resources>
<!-- src/newBrandName/res/values-es/strings.xml -->
<resources>
<string name="app_name">New Brand Name</string>
</resources>Optional overrides: You may still need to override specific strings if your agency has different UI elements. For example, if your agency uses red stop markers instead of green:
<!-- src/newBrandName/res/values/strings.xml -->
<resources>
<string name="app_name">New Brand Name</string>
<!-- Override because our stop dots are red, not green -->
<string name="tutorial_welcome_text">Tap on a stop (red dot on the map) to see arrival times.</string>
</resources>See the agencyX, agencyY, and kiedybus sample flavors for working examples of this pattern.
We provide configuration options in the flavor .gradle files that allow you to choose default behaviors for your brand.
ARRIVAL_INFO_STYLE - Valid values are 0 and 1:
0(Style A) - The original OneBusAway presentation with small rows sorted by estimated arrival time1(Style B) - Groups arrival times by route and shows scheduled arrival times
Users can change the sorting style using the "Sort by" button regardless of the default.
USE_FIXED_REGION - Valid values are true and false:
false- The app works across various regions defined in the Regions API (recommended for most brands)true- The app is fixed to the region information provided in the flavor configuration
USE_PELIAS_GEOCODING - Controls which service is used for searching origins and destinations in trip planning:
true- Uses the Pelias geocoder (configured for geocode.earth by default). Requires a Pelias API key ingradle.properties:Pelias_newBrandName=YOUR_API_KEYfalse- Uses the Google Places SDK. Requires a Google Maps Platform billing account.
See the following flavor files for complete examples:
flavors/agencyX.gradle- Multi-region brand with Style A arrivalsflavors/agencyY.gradle- Fixed-region brand with Style B arrivalsflavors/kiedybus.gradle- Multi-region brand with custom regions API
When launching a rebranded version of OneBusAway, acknowledging that your app is based on the hard work of those contributing to the OneBusAway project is certainly appreciated. However, please do not imply that the OneBusAway project or its contributors endorse the rebranded app, and please do not use the OneBusAway logo or color scheme in your rebranded app.
