|  | 
|  | 1 | +# V2er Android App - GitHub Copilot Instructions | 
|  | 2 | + | 
|  | 3 | +**ALWAYS follow these instructions first and fallback to additional search and context gathering only if the information here is incomplete or found to be in error.** | 
|  | 4 | + | 
|  | 5 | +## Working Effectively | 
|  | 6 | + | 
|  | 7 | +The V2er Android app is a beautiful V2EX client built using MVP architecture with Dagger 2 dependency injection, RxJava, and Retrofit. The app parses HTML responses from V2EX rather than using a JSON API. | 
|  | 8 | + | 
|  | 9 | +### Essential Setup Commands | 
|  | 10 | +Run these commands in sequence to set up the development environment: | 
|  | 11 | + | 
|  | 12 | +```bash | 
|  | 13 | +# Verify Java 17 is installed (required) | 
|  | 14 | +java -version  # Should show Java 17 | 
|  | 15 | + | 
|  | 16 | +# Grant execute permissions to gradlew | 
|  | 17 | +chmod +x gradlew | 
|  | 18 | + | 
|  | 19 | +# Clean and prepare the project | 
|  | 20 | +./gradlew clean --stacktrace | 
|  | 21 | +``` | 
|  | 22 | + | 
|  | 23 | +### Build Commands - **NEVER CANCEL BUILDS** | 
|  | 24 | + | 
|  | 25 | +**CRITICAL: All build commands can take 5-15 minutes. NEVER CANCEL. Set timeouts to 60+ minutes minimum.** | 
|  | 26 | + | 
|  | 27 | +```bash | 
|  | 28 | +# Build debug APK - NEVER CANCEL: Takes 5-10 minutes. Set timeout to 60+ minutes. | 
|  | 29 | +./gradlew assembleDebug --stacktrace | 
|  | 30 | + | 
|  | 31 | +# Build release APK (requires signing configuration) - NEVER CANCEL: Takes 10-15 minutes. Set timeout to 60+ minutes. | 
|  | 32 | +./gradlew assembleRelease --stacktrace | 
|  | 33 | + | 
|  | 34 | +# Clean and rebuild - NEVER CANCEL: Takes 8-12 minutes. Set timeout to 60+ minutes. | 
|  | 35 | +./gradlew clean assembleDebug --stacktrace | 
|  | 36 | + | 
|  | 37 | +# Build App Bundle (AAB) for Play Store - NEVER CANCEL: Takes 10-15 minutes. Set timeout to 60+ minutes. | 
|  | 38 | +./gradlew bundleRelease --stacktrace | 
|  | 39 | +``` | 
|  | 40 | + | 
|  | 41 | +### Testing Commands - **NEVER CANCEL TESTS** | 
|  | 42 | + | 
|  | 43 | +**CRITICAL: Test commands can take 5-20 minutes. NEVER CANCEL. Set timeouts to 30+ minutes minimum.** | 
|  | 44 | + | 
|  | 45 | +```bash | 
|  | 46 | +# Run unit tests - NEVER CANCEL: Takes 3-8 minutes. Set timeout to 30+ minutes. | 
|  | 47 | +./gradlew test --stacktrace | 
|  | 48 | + | 
|  | 49 | +# Run specific variant tests - NEVER CANCEL: Takes 2-5 minutes each. Set timeout to 30+ minutes. | 
|  | 50 | +./gradlew testDebugUnitTest --stacktrace | 
|  | 51 | +./gradlew testReleaseUnitTest --stacktrace | 
|  | 52 | + | 
|  | 53 | +# Run instrumented tests (requires connected device/emulator) - NEVER CANCEL: Takes 10-20 minutes. Set timeout to 45+ minutes. | 
|  | 54 | +./gradlew connectedAndroidTest --stacktrace | 
|  | 55 | +``` | 
|  | 56 | + | 
|  | 57 | +### Linting and Code Quality | 
|  | 58 | + | 
|  | 59 | +```bash | 
|  | 60 | +# Run Android lint checks - Takes 1-3 minutes. Lint is configured with abortOnError false, so errors won't fail builds. | 
|  | 61 | +./gradlew lint --stacktrace | 
|  | 62 | + | 
|  | 63 | +# Note: Lint errors will not fail the build but should be reviewed and fixed when possible. | 
|  | 64 | +``` | 
|  | 65 | + | 
|  | 66 | +### Installation Commands | 
|  | 67 | + | 
|  | 68 | +```bash | 
|  | 69 | +# Install debug build on connected device - Takes 1-2 minutes. | 
|  | 70 | +./gradlew installDebug --stacktrace | 
|  | 71 | + | 
|  | 72 | +# Install release build on connected device - Takes 1-2 minutes. | 
|  | 73 | +./gradlew installRelease --stacktrace | 
|  | 74 | +``` | 
|  | 75 | + | 
|  | 76 | +## Network Connectivity Issues | 
|  | 77 | + | 
|  | 78 | +**IMPORTANT**: If you encounter network connectivity issues with repositories (e.g., "dl.google.com: No address associated with hostname"), document this limitation in your work. The build will fail due to network restrictions in some environments. This is a known limitation and should be noted as "Build commands fail due to network connectivity restrictions in the current environment." | 
|  | 79 | + | 
|  | 80 | +## Validation and Testing Scenarios | 
|  | 81 | + | 
|  | 82 | +After making any changes, ALWAYS run through these validation steps: | 
|  | 83 | + | 
|  | 84 | +### 1. Code Quality Validation | 
|  | 85 | +```bash | 
|  | 86 | +# Always run lint before committing - errors won't fail build but should be reviewed | 
|  | 87 | +./gradlew lint --stacktrace | 
|  | 88 | + | 
|  | 89 | +# Check for compilation errors | 
|  | 90 | +./gradlew compileDebugJava --stacktrace | 
|  | 91 | +``` | 
|  | 92 | + | 
|  | 93 | +### 2. Unit Test Validation - **NEVER CANCEL: Set timeout to 30+ minutes** | 
|  | 94 | +```bash | 
|  | 95 | +# Run all unit tests | 
|  | 96 | +./gradlew test --stacktrace | 
|  | 97 | + | 
|  | 98 | +# Check specific test classes if making focused changes | 
|  | 99 | +./gradlew test --tests="me.ghui.v2er.util.UriUtilsTest" --stacktrace | 
|  | 100 | +``` | 
|  | 101 | + | 
|  | 102 | +### 3. Manual Testing Scenarios | 
|  | 103 | +When making UI or functional changes, manually test these core scenarios: | 
|  | 104 | + | 
|  | 105 | +**Core User Flows to Test:** | 
|  | 106 | +1. **App Launch**: Open the app and verify it loads without crashes | 
|  | 107 | +2. **Topic Browsing**: Navigate through topic lists and verify content loads | 
|  | 108 | +3. **Deep Linking**: Test V2EX URL handling: | 
|  | 109 | +   - `https://v2ex.com/t/*` - Topic pages | 
|  | 110 | +   - `https://v2ex.com/member/*` - User profiles | 
|  | 111 | +   - `https://v2ex.com/go/*` - Node pages | 
|  | 112 | +4. **Theme Switching**: Test both day and night themes | 
|  | 113 | +5. **Image Loading**: Verify images load correctly using Glide | 
|  | 114 | +6. **Network Handling**: Test with poor network conditions | 
|  | 115 | + | 
|  | 116 | +**UI Testing Requirements:** | 
|  | 117 | +- Test on both day and night themes | 
|  | 118 | +- Verify RecyclerView scrolling performance | 
|  | 119 | +- Check custom UI components in `app/src/main/java/me/ghui/v2er/widget/` | 
|  | 120 | +- Ensure proper MVP pattern implementation | 
|  | 121 | + | 
|  | 122 | +## Architecture and Navigation | 
|  | 123 | + | 
|  | 124 | +### Project Structure | 
|  | 125 | +``` | 
|  | 126 | +app/src/main/java/me/ghui/v2er/ | 
|  | 127 | +├── module/           # Feature modules (MVP pattern) | 
|  | 128 | +│   ├── base/        # Base classes for activities/presenters | 
|  | 129 | +│   ├── login/       # Login feature | 
|  | 130 | +│   ├── topic/       # Topic viewing/creation | 
|  | 131 | +│   └── user/        # User profile features | 
|  | 132 | +├── injector/        # Dagger 2 dependency injection | 
|  | 133 | +│   ├── component/   # Dagger components | 
|  | 134 | +│   └── module/      # Dagger modules | 
|  | 135 | +├── network/         # Networking layer | 
|  | 136 | +│   ├── bean/        # Data models (HTML parsing) | 
|  | 137 | +│   └── *.java       # Retrofit services | 
|  | 138 | +├── adapter/         # RecyclerView adapters | 
|  | 139 | +├── widget/          # Custom UI components | 
|  | 140 | +└── util/           # Utility classes | 
|  | 141 | +``` | 
|  | 142 | + | 
|  | 143 | +### Key Files and Locations | 
|  | 144 | + | 
|  | 145 | +**Configuration Files:** | 
|  | 146 | +- `config.gradle` - Version management and build configuration | 
|  | 147 | +- `gradle.properties` - Gradle settings including JVM args for Java 17+ | 
|  | 148 | +- `app/build.gradle` - Main Android build configuration | 
|  | 149 | +- `sentry.properties` - Crash reporting configuration | 
|  | 150 | +- `app/flurry.config` - Analytics configuration | 
|  | 151 | + | 
|  | 152 | +**Important Source Directories:** | 
|  | 153 | +- `app/src/main/java/me/ghui/v2er/module/` - All feature modules following MVP pattern | 
|  | 154 | +- `app/src/main/java/me/ghui/v2er/network/bean/` - Data models that parse V2EX HTML | 
|  | 155 | +- `app/src/main/java/me/ghui/v2er/widget/` - Custom UI components and behaviors | 
|  | 156 | +- `app/src/test/java/` - Unit tests (small test suite) | 
|  | 157 | +- `app/src/androidTest/java/` - Instrumented tests | 
|  | 158 | + | 
|  | 159 | +**MVP Pattern Implementation:** | 
|  | 160 | +Each feature module contains: | 
|  | 161 | +- `Contract.java` - Interface defining View and Presenter contracts | 
|  | 162 | +- `*Activity.java` or `*Fragment.java` - View implementation | 
|  | 163 | +- `*Presenter.java` - Business logic implementation | 
|  | 164 | + | 
|  | 165 | +### Development Guidelines | 
|  | 166 | + | 
|  | 167 | +**Always follow these patterns when making changes:** | 
|  | 168 | + | 
|  | 169 | +1. **MVP Architecture**: Use existing MVP patterns for new features | 
|  | 170 | +2. **Dependency Injection**: Use Dagger 2 for all dependencies | 
|  | 171 | +3. **HTML Parsing**: Use Fruit library annotations for V2EX data parsing | 
|  | 172 | +4. **Async Operations**: Use RxJava 2 for all async operations | 
|  | 173 | +5. **Image Loading**: Use Glide 4 for all image loading operations | 
|  | 174 | +6. **Navigation**: Use Navigator class for activity transitions | 
|  | 175 | + | 
|  | 176 | +**Before committing changes:** | 
|  | 177 | +```bash | 
|  | 178 | +# Always run these validation steps | 
|  | 179 | +./gradlew lint --stacktrace | 
|  | 180 | +./gradlew test --stacktrace | 
|  | 181 | +# Manually test day and night themes | 
|  | 182 | +# Test relevant deep linking scenarios | 
|  | 183 | +``` | 
|  | 184 | + | 
|  | 185 | +## CI/CD Integration | 
|  | 186 | + | 
|  | 187 | +The project uses GitHub Actions for CI/CD: | 
|  | 188 | + | 
|  | 189 | +**Workflows:** | 
|  | 190 | +- `.github/workflows/ci.yml` - Runs tests, lint, and builds on PR/push | 
|  | 191 | +- `.github/workflows/release.yml` - Creates signed releases | 
|  | 192 | +- Uses JDK 17 and caches Gradle dependencies | 
|  | 193 | + | 
|  | 194 | +**Expected CI Timings:** | 
|  | 195 | +- Unit tests: 5-10 minutes | 
|  | 196 | +- Lint checks: 2-5 minutes   | 
|  | 197 | +- Debug build: 8-15 minutes | 
|  | 198 | +- Release build: 10-20 minutes | 
|  | 199 | + | 
|  | 200 | +## Signing Configuration | 
|  | 201 | + | 
|  | 202 | +**For Debug Builds:** | 
|  | 203 | +Use default debug keystore - no additional configuration needed. | 
|  | 204 | + | 
|  | 205 | +**For Release Builds:** | 
|  | 206 | +Requires environment variables (see `SIGNING.md` for details): | 
|  | 207 | +- `KEYSTORE_PASSWORD` - Keystore password | 
|  | 208 | +- `KEY_PASSWORD` - Key password   | 
|  | 209 | +- `KEY_ALIAS` - Key alias (defaults to "ghui") | 
|  | 210 | + | 
|  | 211 | +**Security Note**: Never commit keystore files. The `.gitignore` excludes all `.jks` and `.keystore` files. | 
|  | 212 | + | 
|  | 213 | +## Troubleshooting | 
|  | 214 | + | 
|  | 215 | +### Common Issues and Solutions | 
|  | 216 | + | 
|  | 217 | +1. **Build fails with "dl.google.com: No address associated with hostname"** | 
|  | 218 | +   - This indicates network connectivity restrictions | 
|  | 219 | +   - Document as a known limitation in your work | 
|  | 220 | +   - The CI/CD environment has proper connectivity | 
|  | 221 | + | 
|  | 222 | +2. **Java compatibility issues** | 
|  | 223 | +   - Ensure Java 17 is being used | 
|  | 224 | +   - The `gradle.properties` file contains required JVM args for Java 17+ | 
|  | 225 | + | 
|  | 226 | +3. **Dagger compilation errors** | 
|  | 227 | +   - Clean and rebuild: `./gradlew clean assembleDebug` | 
|  | 228 | +   - Check that all `@Inject` and `@Provides` annotations are correct | 
|  | 229 | + | 
|  | 230 | +4. **RxJava threading issues** | 
|  | 231 | +   - Ensure proper use of `.observeOn(AndroidSchedulers.mainThread())` | 
|  | 232 | +   - Use RxLifecycle for automatic subscription management | 
|  | 233 | + | 
|  | 234 | +5. **HTML parsing failures** | 
|  | 235 | +   - Check Fruit annotations in `network/bean/` classes | 
|  | 236 | +   - V2EX may have changed their HTML structure | 
|  | 237 | + | 
|  | 238 | +### Performance Considerations | 
|  | 239 | + | 
|  | 240 | +- **Large RecyclerViews**: Use `SpeedyLinearLayoutManager` for improved scrolling | 
|  | 241 | +- **Image Loading**: Glide is configured with OkHttp integration for better performance | 
|  | 242 | +- **Memory**: Proguard and resource shrinking are enabled for release builds | 
|  | 243 | + | 
|  | 244 | +## Key Technologies and Versions | 
|  | 245 | + | 
|  | 246 | +- **Language**: Java 8 (source/target compatibility) | 
|  | 247 | +- **Build System**: Gradle 8.13 with Android Gradle Plugin | 
|  | 248 | +- **Minimum SDK**: API 27 (Android 8.1) | 
|  | 249 | +- **Target SDK**: API 36 | 
|  | 250 | +- **Compile SDK**: API 36 | 
|  | 251 | + | 
|  | 252 | +**Core Dependencies:** | 
|  | 253 | +- **DI**: Dagger 2.57 | 
|  | 254 | +- **Networking**: Retrofit 3.0.0 + OkHttp 5.1.0 + RxJava 2.2.21 | 
|  | 255 | +- **View Binding**: ButterKnife 10.2.3 | 
|  | 256 | +- **Image Loading**: Glide 4.16.0 | 
|  | 257 | +- **HTML Parsing**: Fruit 1.0.4 (custom library) | 
|  | 258 | +- **Event Bus**: EventBus 3.3.1 | 
|  | 259 | + | 
|  | 260 | +## Distribution | 
|  | 261 | + | 
|  | 262 | +- **Google Play Store**: https://play.google.com/store/apps/details?id=me.ghui.v2er | 
|  | 263 | +- **CoolApk**: https://www.coolapk.com/apk/me.ghui.v2er | 
|  | 264 | + | 
|  | 265 | +The app is distributed under GPL license. See `LICENSE` file for details. | 
0 commit comments