zhanghai/Douya
开源的 Material Design 豆瓣客户端(A Material Design app for douban.com)
Looks unmaintained — solo project with stale commits
weakest axisno license — legally unclear; last commit was 5y ago…
no license — can't legally use code; no tests detected…
Documented and popular — useful reference codebase to read through.
no license — can't legally use code; last commit was 5y ago
- ✓CI configured
- ⚠Stale — last commit 5y ago
- ⚠Solo or near-solo (1 contributor active in recent commits)
Show all 5 evidence items →Show less
- ⚠No license — legally unclear to depend on
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: publish a permissive license (MIT, Apache-2.0, etc.)
- →Fork & modify Concerns → Mixed if: add a LICENSE file
- →Deploy as-is Concerns → Mixed if: add a LICENSE file
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Great to learn from" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/zhanghai/douya)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/zhanghai/douya on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: zhanghai/Douya
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/zhanghai/Douya shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
AVOID — Looks unmaintained — solo project with stale commits
- CI configured
- ⚠ Stale — last commit 5y ago
- ⚠ Solo or near-solo (1 contributor active in recent commits)
- ⚠ No license — legally unclear to depend on
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live zhanghai/Douya
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/zhanghai/Douya.
What it runs against: a local clone of zhanghai/Douya — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in zhanghai/Douya | Confirms the artifact applies here, not a fork |
| 2 | Default branch master exists | Catches branch renames |
| 3 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 4 | Last commit ≤ 1819 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of zhanghai/Douya. If you don't
# have one yet, run these first:
#
# git clone https://github.com/zhanghai/Douya.git
# cd Douya
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of zhanghai/Douya and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "zhanghai/Douya(\\.git)?\\b" \\
&& ok "origin remote is zhanghai/Douya" \\
|| miss "origin remote is not zhanghai/Douya (artifact may be from a fork)"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "app/src/main/java/me/zhanghai/android/douya/DouyaApplication.java" \\
&& ok "app/src/main/java/me/zhanghai/android/douya/DouyaApplication.java" \\
|| miss "missing critical file: app/src/main/java/me/zhanghai/android/douya/DouyaApplication.java"
test -f "app/src/main/java/me/zhanghai/android/douya/account/app/Authenticator.java" \\
&& ok "app/src/main/java/me/zhanghai/android/douya/account/app/Authenticator.java" \\
|| miss "missing critical file: app/src/main/java/me/zhanghai/android/douya/account/app/Authenticator.java"
test -f "app/src/main/java/me/zhanghai/android/douya/broadcast/content/BroadcastResource.java" \\
&& ok "app/src/main/java/me/zhanghai/android/douya/broadcast/content/BroadcastResource.java" \\
|| miss "missing critical file: app/src/main/java/me/zhanghai/android/douya/broadcast/content/BroadcastResource.java"
test -f "app/src/main/java/me/zhanghai/android/douya/broadcast/ui/BroadcastListFragment.java" \\
&& ok "app/src/main/java/me/zhanghai/android/douya/broadcast/ui/BroadcastListFragment.java" \\
|| miss "missing critical file: app/src/main/java/me/zhanghai/android/douya/broadcast/ui/BroadcastListFragment.java"
test -f "app/build.gradle" \\
&& ok "app/build.gradle" \\
|| miss "missing critical file: app/build.gradle"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1819 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1789d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/zhanghai/Douya"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Douya is a Material Design Android client for Douban (豆瓣), a Chinese social network for movies, books, music, and events. It prioritizes friend-based content discovery through broadcasts and neighbor feeds rather than algorithmic recommendations, implementing native Android patterns with custom Material Design components like ExpandedHintTextInputLayout and ThemedSwipeRefreshLayout. Monolithic Android app module (app/) with package hierarchy mirroring feature domains: account/ (authentication via AccountManager), broadcast/ (friend feeds), and custom widgets in androidx/ namespace overrides (NightModeAccessor, FriendlySwipeRefreshLayout). Core app state via Resources and AccountPreferences; networking through Douban API v2 REST calls.
👥Who it's for
Chinese Android developers and Douban power users who want a Material Design-first mobile experience focused on friend networks and broadcasts rather than the official Douban app's item-centric approach. Contributors interested in Android architecture patterns, Material Design implementation, and internationalization (English and Chinese).
🌱Maturity & risk
Actively maintained but approaching stability: last version tagged 1.0.0-beta.12 (versionCode 15), Travis CI configured for automated builds, ProGuard minification enabled for release builds, but no visible test suite in the file structure. The codebase is production-ready for Douban's Chinese user base but still in beta versioning.
Moderate dependency risk: relies on Crashlytics/Fabric (Firebase) for crash reporting, Douban's V2 API (not versioned in build.gradle visible snippet), and custom Material Design components that may diverge from library updates. Single maintainer (zhanghai) with infrequent but stable commits; no visible open issue backlog in provided data; compileSdkVersion 29 and targetSdkVersion 29 are dated (current is 34+).
Active areas of work
No active development visible in provided data; repo appears stable post-beta with focus on maintenance. Last observable state: Travis CI passing, Gradle build configured with Crashlytics integration, but no evidence of recent commits or open PRs in file snapshot.
🚀Get running
Clone and build via Gradle: git clone https://github.com/zhanghai/Douya.git && cd Douya && ./gradlew assembleDebug. Requires Java 8 (sourceCompatibility/targetCompatibility set to VERSION_1_8), Android SDK 21-29, and setup of signing.gradle for release builds. API keys must be configured separately per DouyaApiKey guide in README.
Daily commands:
./gradlew assembleDebug && adb install -r app/build/outputs/apk/debug/app-debug.apk to build and install on connected device. Dev build has Crashlytics disabled (ext.enableCrashlytics = false in debug buildType).
🗺️Map of the codebase
app/src/main/java/me/zhanghai/android/douya/DouyaApplication.java— Application entry point and global initialization; all contributors must understand the app lifecycle and dependency setup here.app/src/main/java/me/zhanghai/android/douya/account/app/Authenticator.java— Core authentication logic for Douban API; essential for understanding how credentials are managed and API requests are authenticated.app/src/main/java/me/zhanghai/android/douya/broadcast/content/BroadcastResource.java— Base resource class for broadcast data management; establishes the pattern for all content fetching and caching in the app.app/src/main/java/me/zhanghai/android/douya/broadcast/ui/BroadcastListFragment.java— Primary UI fragment for displaying broadcasts; demonstrates the fragment architecture and UI state management used throughout.app/build.gradle— Project build configuration with SDK versions, dependencies, and app settings; critical for build reproducibility and dependency management.app/src/main/AndroidManifest.xml— Android manifest declaring all activities, services, permissions, and providers; foundational for understanding app capabilities and entry points.app/src/main/java/me/zhanghai/android/douya/app/RetainedFragment.java— Base retained fragment for data persistence across configuration changes; core pattern used throughout for lifecycle management.
🛠️How to make changes
Add a new broadcast list screen (e.g., User broadcasts)
- Create a new Resource class extending BaseBroadcastListResource in broadcast/content/ (
app/src/main/java/me/zhanghai/android/douya/broadcast/content/) - Create a new Fragment extending BaseTimelineBroadcastListFragment in broadcast/ui/ (
app/src/main/java/me/zhanghai/android/douya/broadcast/ui/BaseTimelineBroadcastListFragment.java) - Register the new fragment in the navigation and create an Activity if needed (
app/src/main/java/me/zhanghai/android/douya/broadcast/ui/BroadcastListActivity.java) - Add manifest entries for the new Activity (
app/src/main/AndroidManifest.xml)
Add a new write action (create/update/delete) for broadcasts
- Create a Manager class extending the pattern of SendBroadcastManager (
app/src/main/java/me/zhanghai/android/douya/broadcast/content/SendBroadcastManager.java) - Create a Writer class handling the actual API call (
app/src/main/java/me/zhanghai/android/douya/broadcast/content/SendBroadcastWriter.java) - Create dialog fragments for confirmation if needed (see ConfirmDeleteBroadcastDialogFragment) (
app/src/main/java/me/zhanghai/android/douya/broadcast/ui/ConfirmDeleteBroadcastDialogFragment.java) - Integrate Manager into UI layer via Activity/Fragment (
app/src/main/java/me/zhanghai/android/douya/broadcast/ui/SendBroadcastActivity.java)
Add authentication or account management features
- Modify the Authenticator class to handle new authentication requirements (
app/src/main/java/me/zhanghai/android/douya/account/app/Authenticator.java) - Update AuthenticatorActivity UI to match Material Design theme (
app/src/main/java/me/zhanghai/android/douya/account/ui/AuthenticatorActivity.java) - Update AccountUtils with any new account-related utility methods (
app/src/main/java/me/zhanghai/android/douya/account/util/AccountUtils.java) - Update manifest with new account-related permissions (
app/src/main/AndroidManifest.xml)
Extend the caching strategy for better performance
- Study the existing HomeBroadcastListCache pattern (
app/src/main/java/me/zhanghai/android/douya/broadcast/content/HomeBroadcastListCache.java) - Create a similar cache class for your new data type (
app/src/main/java/me/zhanghai/android/douya/broadcast/content/) - Integrate the cache into the corresponding Resource class (
app/src/main/java/me/zhanghai/android/douya/broadcast/content/HomeBroadcastListResource.java) - Clear cache on relevant write operations in Manager classes (
app/src/main/java/me/zhanghai/android/douya/broadcast/content/SendBroadcastManager.java)
🪤Traps & gotchas
signing.gradle is not included in file list but required for release builds (apply from: '../signing.gradle'); will cause build failure if missing. Douban API keys must be obtained separately and configured (see DouyaApiKey repo in README). ProGuard minification enabled in release; local.properties required for signing configuration. AccountManager API requires ACCOUNT permissions and device account setup. Custom androidx overrides may conflict with updated androidx library versions.
🏗️Architecture
💡Concepts to learn
- Android AccountManager Authentication — Douya uses AccountManager (Authenticator.java, AuthenticatorService.java) to handle Douban OAuth without storing credentials directly; essential for secure multi-account support and Android account sync integration
- Material Design System & Custom Components — Douya's core philosophy is pixel-perfect Material Design; files like ExpandedHintTextInputLayout and ThemedSwipeRefreshLayout show how to extend Material library components for app-specific theming
- ProGuard Code Obfuscation & Minification — Release builds use ProGuard (minifyEnabled true in build.gradle) with custom rules (proguard-rules.pro) to shrink APK size and protect proprietary code; requires careful configuration to avoid breaking Douban API serialization
- Fragment-based Navigation Architecture — Douya structures UI around Fragments (AuthenticatorFragment, TargetedRetainedFragment, RetainedFragment) for tablet multi-pane layouts and screen rotation handling; critical for flexible navigation across device sizes
- Android FileProvider for Content Sharing — ImageTypeFileProvider (app/src/main/java/me/zhanghai/android/douya/app/ImageTypeFileProvider.java) uses FileProvider to safely share images across apps without exposing raw file paths; required for Android 7.0+ security scoping
- REST API Resource Pattern — ApiV2BroadcastListResource exemplifies Douya's network layer: each entity type (broadcasts, users, comments) has a Resource class that encapsulates API calls, caching, and error handling; abstraction that decouples UI from HTTP details
- Retained Fragments for State Persistence — RetainedFragment and TargetedRetainedFragment classes survive configuration changes (screen rotation); Douya uses these to persist network requests and UI state across lifecycle events without data loss
🔗Related repos
zhanghai/DouyaApiKey— Official guide for obtaining and configuring Douban API keys required to run Douyazhanghai/DouyaCiBuilds— CI build artifacts and releases for Douya; distribution channel for beta and stable APKsandroid/architecture-samples— Google's official Android architecture guidance; Douya's pattern of Activities, Fragments, and Resources aligns with these samplesmaterial-components/material-components-android— Upstream Material Design library; Douya extends components like SwipeRefreshLayout from this librarychrisbanes/PhotoView— Direct dependency (com.github.chrisbanes:PhotoView:2.3.0) used in Douya for zoomable image galleries
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Migrate from Fabric Crashlytics to Firebase Crashlytics
The build.gradle file shows the project uses deprecated Fabric Crashlytics (io.fabric.tools:gradle and com.crashlytics.sdk.android:answers:1.4.6). Fabric was sunset and migrated to Firebase. This is a concrete, valuable modernization that improves dependency maintenance and future compatibility. The migration involves updating build.gradle, AndroidManifest.xml, and any crash reporting initialization code in DouyaApplication.java.
- [ ] Update build.gradle: replace io.fabric plugin with com.google.gms:google-services plugin
- [ ] Add Firebase Crashlytics dependency to build.gradle (com.google.firebase:firebase-crashlytics)
- [ ] Create google-services.json file for Firebase configuration
- [ ] Update DouyaApplication.java to initialize Firebase Crashlytics instead of Fabric Answers
- [ ] Remove legacy Fabric maven repository and classpath dependencies from build.gradle
- [ ] Test crash reporting functionality in debug and release builds
Add missing unit tests for account authentication flow
The codebase has multiple authentication-related classes (AuthenticatorActivity.java, AuthenticateRequest.java, AccountPreferences.java, AuthenticatorUtils.java) but there is no visible test directory structure. Adding unit tests for the account module would improve reliability of sensitive authentication logic. This is critical for a login-required app like a Douban client.
- [ ] Create app/src/test/java/me/zhanghai/android/douya/account directory structure
- [ ] Add unit tests for AccountPreferences.java covering preference read/write operations
- [ ] Add unit tests for AuthenticatorUtils.java covering token validation and credential handling
- [ ] Add unit tests for AuthenticateRequest.java covering request building and response parsing
- [ ] Configure build.gradle with testImplementation for JUnit and Mockito
- [ ] Ensure tests can run via gradle test command
Add GitHub Actions CI/CD workflow to replace Travis CI
The project uses Travis CI (.travis.yml) which has become less favorable compared to GitHub Actions. GitHub Actions is free, integrated with GitHub, and more flexible. Creating a GitHub Actions workflow would modernize the CI/CD pipeline while maintaining the existing build verification that Travis currently provides.
- [ ] Create .github/workflows/android-build.yml with steps to checkout code, setup Java/Android SDK
- [ ] Configure gradle build task for debug APK and run lint/unit tests
- [ ] Add caching for gradle dependencies to speed up builds
- [ ] Optional: Add step to upload build artifacts or APKs to workflow artifacts
- [ ] Test the workflow triggers properly on push and pull requests
- [ ] Update README.md to replace Travis CI badge with GitHub Actions badge
- [ ] Keep .travis.yml during transition period or remove after verification
🌿Good first issues
- Add unit tests for ApiV2BroadcastListResource.java and other Resource classes under broadcast/content/ to verify API response parsing and error handling (no test/ directory visible in file structure)
- Update compileSdkVersion and targetSdkVersion from 29 to 34 and test against Android 14 APIs, fixing any deprecation warnings in deprecated Account class usage (Authenticator.java)
- Document the Douban API v2 endpoint contracts used by each *Resource class (e.g., ApiV2BroadcastListResource) in a CONTRIBUTING.md guide with example requests/responses to ease onboarding
📝Recent commits
Click to expand
Recent commits
14d2f3e— [Fix] Fix ViewUtils.getColorStateListFromAttrRes(). (zhanghai)e9916a9— [Feature] Target API 29. (zhanghai)cd35eda— [Feature] Update preference dependencies. (zhanghai)6ef58ac— [Feature] Update dependencies. (zhanghai)c395bcc— [Feature] Make API keys built in. (zhanghai)d795e3f— [Refactor] Sync code. (zhanghai)4c4ddab— [Refactor] Remove pre-21 resources. (zhanghai)1f7e07e— [Feature] Bump minSdkVersion to 21. (zhanghai)748b9b6— [Feature] Update dependencies. (zhanghai)205d40a— [Feature] Update dependency. (zhanghai)
🔒Security observations
The Douya codebase has significant security concerns primarily related to outdated and deprecated dependencies. The most critical issues are: (1) use of obsolete Crashlytics SDK that is no longer maintained, (2) open-ended Fabric Gradle plugin version that can auto-update to insecure versions, (3) outdated build tools and target SDK version not meeting current standards. The project also shows
- High · Outdated Build Tools and Deprecated Gradle Plugin —
app/build.gradle. The project uses buildToolsVersion '28.0.3' (deprecated) and compileSdkVersion 29 (outdated). More critically, it uses 'io.fabric:gradle:1.+' with an open-ended version specification, which can introduce breaking changes and security issues automatically. Fix: Update to latest stable buildToolsVersion (e.g., 34.0.0+), compileSdkVersion 34+, and pin Fabric Gradle plugin to a specific secure version or migrate to Firebase Crashlytics. - High · Insecure Dependency Version Management —
app/build.gradle (buildscript dependencies). The Fabric Gradle plugin uses an open-ended version constraint 'classpath 'io.fabric.tools:gradle:1.+'' which bypasses security controls and can auto-update to potentially compromised versions without developer awareness. Fix: Replace 'io.fabric.tools:gradle:1.+' with a pinned version like 'io.fabric.tools:gradle:1.31.2' or migrate to Firebase Crashlytics which is the recommended replacement. - High · Outdated Crashlytics SDK —
app/build.gradle (dependencies). The project uses 'com.crashlytics.sdk.android:answers:1.4.6' which is obsolete. Crashlytics SDK was deprecated and merged into Firebase. This version has known vulnerabilities and is no longer maintained. Fix: Migrate to Firebase Crashlytics SDK (com.google.firebase:firebase-crashlytics). The legacy Crashlytics SDK is no longer supported. - Medium · Incomplete Dependency Declaration —
app/build.gradle (line ending with 'implementation' only). The build.gradle file has an incomplete dependency declaration: 'implementation' with no artifact specified. This indicates potential build issues and incomplete migration. Fix: Complete the dependency declaration by specifying the artifact name and version. Remove the orphaned line if not needed. - Medium · Missing ProGuard/R8 Configuration for Third-Party Libraries —
app/build.gradle and app/proguard-rules.pro. While proguard-rules.pro exists, there's no evidence of specific rules for external dependencies like PhotoView, LunarCalendar, and Crashlytics which may have reflection-heavy code. Fix: Ensure proguard-rules.pro includes proper keep rules for all third-party libraries, especially those using reflection or serialization. - Medium · Outdated Target SDK Version —
app/build.gradle (defaultConfig). targetSdkVersion is set to 29 (released in 2019). Modern Android requires targeting recent API levels to access Google Play Store and ensure compatibility with security patches. Fix: Update targetSdkVersion to 34 or higher to meet current Google Play Store requirements and benefit from latest security features. - Low · Potential Signing Configuration Exposure —
app/build.gradle (apply from: '../signing.gradle'). The build script references '../signing.gradle' for release signing configuration. If this file contains credentials or keystore passwords, they could be exposed in version control. Fix: Ensure signing.gradle uses environment variables or secure credential management. Never commit keystore passwords or signing keys to version control. - Low · Insecure Maven Repository Configuration —
app/build.gradle (repositories section). The project uses JitPack (https://jitpack.io) which builds and hosts GitHub repositories on-the-fly. While convenient, this introduces supply chain risk if upstream repositories are compromised. Fix: Verify JitPack dependencies are from trusted sources. Consider using Maven Central or official repositories when available. Implement dependency verification.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.