@leejungkiin/awkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +146 -0
- package/VERSION +1 -0
- package/bin/awf.js +549 -0
- package/bin/awk.js +1759 -0
- package/core/AGENTS.md +39 -0
- package/core/GEMINI.md +202 -0
- package/core/GEMINI.md.bak +244 -0
- package/core/orchestrator.md +58 -0
- package/package.json +46 -0
- package/schemas/brain.schema.json +342 -0
- package/schemas/preferences.schema.json +95 -0
- package/schemas/session.schema.json +112 -0
- package/skill-packs/neural-memory/README.md +111 -0
- package/skill-packs/neural-memory/pack.json +35 -0
- package/skill-packs/neural-memory/schemas/brain-snapshot.json +167 -0
- package/skill-packs/neural-memory/skills/nm-memory-audit/SKILL.md +157 -0
- package/skill-packs/neural-memory/skills/nm-memory-evolution/SKILL.md +202 -0
- package/skill-packs/neural-memory/skills/nm-memory-intake/SKILL.md +135 -0
- package/skill-packs/neural-memory/skills/nm-memory-sync/SKILL.md +184 -0
- package/skill-packs/neural-memory/workflows/nm-import.md +73 -0
- package/skill-packs/neural-memory/workflows/nm-recall.md +67 -0
- package/skill-packs/neural-memory/workflows/nm-snapshot.md +69 -0
- package/skills/adaptive-language/SKILL.md +189 -0
- package/skills/ambient-brain/SKILL.md +314 -0
- package/skills/ambient-brain/brain-router.md +185 -0
- package/skills/ambient-brain/brain-templates.md +201 -0
- package/skills/auto-save/SKILL.md +223 -0
- package/skills/awf-adaptive-language/SKILL.md +189 -0
- package/skills/awf-context-help/SKILL.md +180 -0
- package/skills/awf-error-translator/SKILL.md +153 -0
- package/skills/awf-session-restore/SKILL.md +270 -0
- package/skills/awf-version-tracker/SKILL.md +32 -0
- package/skills/awf-version-tracker/scripts/snapshot.sh +22 -0
- package/skills/beads-manager/SKILL.md +323 -0
- package/skills/brainstorm-agent/SKILL.md +295 -0
- package/skills/context-help/SKILL.md +180 -0
- package/skills/error-translator/SKILL.md +153 -0
- package/skills/ios-engineer/SKILL.md +101 -0
- package/skills/memory-sync/SKILL.md +378 -0
- package/skills/memory-sync/memory-router.md +185 -0
- package/skills/memory-sync/memory-templates.md +201 -0
- package/skills/orchestrator/SKILL.md +193 -0
- package/skills/session-restore/SKILL.md +240 -0
- package/templates/CODEBASE.md +80 -0
- package/templates/brain.example.json +321 -0
- package/templates/preferences.example.json +21 -0
- package/templates/project-identity/android.json +28 -0
- package/templates/project-identity/backend-nestjs.json +24 -0
- package/templates/project-identity/expo.json +27 -0
- package/templates/project-identity/ios.json +27 -0
- package/templates/project-identity/web-nextjs.json +24 -0
- package/templates/session.example.json +53 -0
- package/templates/specs/design-template.md +166 -0
- package/templates/specs/requirements-template.md +65 -0
- package/templates/specs/tasks-template.md +132 -0
- package/templates/structures/android.txt +10 -0
- package/templates/structures/backend-nestjs.txt +6 -0
- package/templates/structures/expo.txt +9 -0
- package/templates/structures/ios.txt +9 -0
- package/templates/structures/web-nextjs.txt +6 -0
- package/templates/workflow_dual_mode_template.md +87 -0
- package/workflows/_uncategorized/README.md +339 -0
- package/workflows/_uncategorized/ads-creative.md +357 -0
- package/workflows/_uncategorized/ads-full-optimization.md +308 -0
- package/workflows/_uncategorized/ads-plan.md +247 -0
- package/workflows/_uncategorized/ads-user-analysis.md +337 -0
- package/workflows/_uncategorized/skill-health.md +35 -0
- package/workflows/_uncategorized/skill-rollback.md +35 -0
- package/workflows/ads/admob.md +62 -0
- package/workflows/ads/ads-analyst.md +201 -0
- package/workflows/ads/ads-audit.md +106 -0
- package/workflows/ads/ads-optimize.md +97 -0
- package/workflows/ads/ads-targeting.md +241 -0
- package/workflows/ads/adsExpert.md +160 -0
- package/workflows/ads/smali-ads-config.md +400 -0
- package/workflows/ads/smali-ads-flow.md +331 -0
- package/workflows/ads/smali-ads-interstitial.md +377 -0
- package/workflows/ads/smali-ads-native.md +382 -0
- package/workflows/context/auto-execution-workflow.md +291 -0
- package/workflows/context/auto-implement.md +211 -0
- package/workflows/context/codebase-sync.md +163 -0
- package/workflows/context/logic-reasoning-workflow.md +260 -0
- package/workflows/context/next.md +195 -0
- package/workflows/context/recap.md +212 -0
- package/workflows/context/save-brain.md +285 -0
- package/workflows/context/user-intent-analysis-workflow.md +206 -0
- package/workflows/expert/codeExpert.md +126 -0
- package/workflows/expert/debugExpert.md +136 -0
- package/workflows/expert/planExpert.md +112 -0
- package/workflows/git/cloudflare-tunnel.md +135 -0
- package/workflows/git/git-commit-workflow.md +75 -0
- package/workflows/git/hotfix.md +357 -0
- package/workflows/git/release-notes.md +160 -0
- package/workflows/git/rollback.md +52 -0
- package/workflows/git/smart-git-ops.md +103 -0
- package/workflows/lifecycle/brainstorm.md +377 -0
- package/workflows/lifecycle/code.md +663 -0
- package/workflows/lifecycle/debug.md +116 -0
- package/workflows/lifecycle/deploy.md +95 -0
- package/workflows/lifecycle/init.md +152 -0
- package/workflows/lifecycle/master-code-workflow.md +300 -0
- package/workflows/lifecycle/migration.md +196 -0
- package/workflows/lifecycle/plan.md +91 -0
- package/workflows/lifecycle/refactor.md +165 -0
- package/workflows/lifecycle/run.md +52 -0
- package/workflows/lifecycle/test.md +91 -0
- package/workflows/meta/customize.md +346 -0
- package/workflows/meta/file-protection-rules.md +129 -0
- package/workflows/meta/help.html +350 -0
- package/workflows/meta/project-identity-enforcement.md +180 -0
- package/workflows/mobile/app-analysis.md +64 -0
- package/workflows/mobile/maestro-qa-workflow.md +470 -0
- package/workflows/mobile/maestro-test-workflow.md +84 -0
- package/workflows/mobile/structure-clean-architect.md +271 -0
- package/workflows/mobile/turbo-mobile-build.md +190 -0
- package/workflows/quality/accessibility-audit.md +311 -0
- package/workflows/quality/audit.md +217 -0
- package/workflows/quality/bug-hunter.md +243 -0
- package/workflows/quality/code-janitor.md +209 -0
- package/workflows/quality/code-quality-rules.md +132 -0
- package/workflows/quality/performance-audit.md +343 -0
- package/workflows/quality/project-audit.md +61 -0
- package/workflows/quality/self-healing-test.md +192 -0
- package/workflows/quality/ui-review.md +130 -0
- package/workflows/quality/ux-audit.md +213 -0
- package/workflows/quality/visual-debug.md +34 -0
- package/workflows/roles/oracle.md +267 -0
- package/workflows/roles/product-manager-workflow.md +52 -0
- package/workflows/roles/qa-engineer-workflow.md +41 -0
- package/workflows/roles/tech-lead-workflow.md +45 -0
- package/workflows/roles/ui-ux-designer-workflow.md +42 -0
- package/workflows/roles/vibe-coding-master-workflow.md +52 -0
- package/workflows/ui/app-screen-analyzer.md +152 -0
- package/workflows/ui/create-feature.md +332 -0
- package/workflows/ui/create-spec-architect.md +184 -0
- package/workflows/ui/design-to-ui.md +308 -0
- package/workflows/ui/ui-first-methodology.md +279 -0
- package/workflows/ui/visualize.md +298 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: ⚙️ Remote Config cho Ad Settings - Điều chỉnh ads mà không cần rebuild APK
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Smali Ads Remote Config
|
|
6
|
+
|
|
7
|
+
> **🎯 Mục tiêu**: Setup Remote Config để điều chỉnh ad settings (frequency, ad units, enable/disable) từ xa.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 📋 Overview - Tại sao cần Remote Config?
|
|
12
|
+
|
|
13
|
+
### Benefits
|
|
14
|
+
|
|
15
|
+
| Without Remote Config | With Remote Config |
|
|
16
|
+
|----------------------|-------------------|
|
|
17
|
+
| ❌ Hardcode ad unit IDs | ✅ Update ad IDs remotely |
|
|
18
|
+
| ❌ Fixed frequency (3-5) | ✅ Adjust frequency dynamic |
|
|
19
|
+
| ❌ Rebuild APK để thay đổi | ✅ Change instantly |
|
|
20
|
+
| ❌ Rollback = new release | ✅ Rollback = change config |
|
|
21
|
+
| ❌ A/B test = multiple APKs | ✅ A/B test via config |
|
|
22
|
+
|
|
23
|
+
### Use Cases
|
|
24
|
+
|
|
25
|
+
1. **Update Ad Unit IDs** - Khi switch AdMob account
|
|
26
|
+
2. **Adjust Frequency** - Optimize revenue vs UX
|
|
27
|
+
3. **Feature Flags** - Enable/disable ads per screen
|
|
28
|
+
4. **A/B Testing** - Test different strategies
|
|
29
|
+
5. **Emergency Kill Switch** - Disable ads if issues
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 🔍 Phase 1: Choose Config Strategy
|
|
34
|
+
|
|
35
|
+
### Option 1: Firebase Remote Config (Recommended)
|
|
36
|
+
|
|
37
|
+
**Pros:**
|
|
38
|
+
- Free tier available
|
|
39
|
+
- Real-time updates
|
|
40
|
+
- User targeting (country, app version, etc.)
|
|
41
|
+
- Analytics integration
|
|
42
|
+
- No server needed
|
|
43
|
+
|
|
44
|
+
**Cons:**
|
|
45
|
+
- Requires Firebase SDK
|
|
46
|
+
- Network dependency
|
|
47
|
+
- Có thể conflict nếu app đã có Firebase
|
|
48
|
+
|
|
49
|
+
**Best for**: Production apps, need targeting
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### Option 2: JSON from Server
|
|
54
|
+
|
|
55
|
+
**Pros:**
|
|
56
|
+
- Full control
|
|
57
|
+
- Lightweight
|
|
58
|
+
- Custom logic
|
|
59
|
+
- No third-party dependency
|
|
60
|
+
|
|
61
|
+
**Cons:**
|
|
62
|
+
- Need own server/CDN
|
|
63
|
+
- Implement sync logic
|
|
64
|
+
- Không có targeting built-in
|
|
65
|
+
|
|
66
|
+
**Best for**: Apps có backend riêng
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### Option 3: Assets Fallback + Remote
|
|
71
|
+
|
|
72
|
+
**Strategy**: Local JSON fallback + remote override
|
|
73
|
+
|
|
74
|
+
**Pros:**
|
|
75
|
+
- App works offline
|
|
76
|
+
- Fast first load
|
|
77
|
+
- Graceful degradation
|
|
78
|
+
|
|
79
|
+
**Implementation:**
|
|
80
|
+
```
|
|
81
|
+
1. Load from assets/ad_config.json (defaults)
|
|
82
|
+
2. Fetch from remote
|
|
83
|
+
3. Merge/override
|
|
84
|
+
4. Cache locally
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Best for**: Hybrid approach, production ready
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 🔧 Phase 2: Config Schema Design
|
|
92
|
+
|
|
93
|
+
### 2.1. JSON Structure
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"version": "1.0",
|
|
98
|
+
"last_updated": "2024-01-20T10:00:00Z",
|
|
99
|
+
|
|
100
|
+
"ad_units": {
|
|
101
|
+
"interstitial": {
|
|
102
|
+
"splash": "ca-app-pub-XXX/111",
|
|
103
|
+
"onboarding": "ca-app-pub-XXX/222",
|
|
104
|
+
"general": "ca-app-pub-XXX/333"
|
|
105
|
+
},
|
|
106
|
+
"native": {
|
|
107
|
+
"onboarding": "ca-app-pub-XXX/444",
|
|
108
|
+
"list": "ca-app-pub-XXX/555"
|
|
109
|
+
},
|
|
110
|
+
"banner": {
|
|
111
|
+
"home": "ca-app-pub-XXX/666"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
"frequency": {
|
|
116
|
+
"interstitial": {
|
|
117
|
+
"min_launches": 3,
|
|
118
|
+
"max_launches": 5,
|
|
119
|
+
"min_interval_ms": 10000
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
"feature_flags": {
|
|
124
|
+
"enable_splash_ad": true,
|
|
125
|
+
"enable_onboarding_ad": true,
|
|
126
|
+
"enable_random_inter": true,
|
|
127
|
+
"enable_native_ads": true
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
"test_mode": {
|
|
131
|
+
"enabled": false,
|
|
132
|
+
"use_test_ads": false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 2.2. Config Keys Strategy
|
|
138
|
+
|
|
139
|
+
**Naming convention:**
|
|
140
|
+
```
|
|
141
|
+
{feature}_{type}_{location}
|
|
142
|
+
|
|
143
|
+
Examples:
|
|
144
|
+
- ad_inter_splash
|
|
145
|
+
- ad_native_onboarding
|
|
146
|
+
- freq_inter_min
|
|
147
|
+
- flag_enable_ads
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 📦 Phase 3: Implementation
|
|
153
|
+
|
|
154
|
+
### 3.1. Discovery - Check Firebase Presence
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Check if Firebase already in APK
|
|
158
|
+
find smali* -path "*/com/google/firebase/*" -type d
|
|
159
|
+
|
|
160
|
+
# Check Firebase config
|
|
161
|
+
ls assets/google-services.json 2>/dev/null
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Scenarios:**
|
|
165
|
+
|
|
166
|
+
**A. Firebase đã có**
|
|
167
|
+
- Reuse existing Firebase instance
|
|
168
|
+
- Add Remote Config component
|
|
169
|
+
- Risk: Conflict với existing config
|
|
170
|
+
|
|
171
|
+
**B. Firebase chưa có**
|
|
172
|
+
- Add Firebase SDK (heavy ~5-10MB)
|
|
173
|
+
- Setup google-services.json
|
|
174
|
+
- Risk: Method count, size increase
|
|
175
|
+
|
|
176
|
+
**C. Custom server**
|
|
177
|
+
- Implement HTTP client
|
|
178
|
+
- Parse JSON
|
|
179
|
+
- Cache mechanism
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### 3.2. Config Helper Class
|
|
184
|
+
|
|
185
|
+
**Create wrapper:**
|
|
186
|
+
```
|
|
187
|
+
{SDK_DIR}/config/RemoteConfigHelper.smali
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Methods needed:**
|
|
191
|
+
```smali
|
|
192
|
+
.method public static init(Context)V
|
|
193
|
+
# Initialize config (Firebase or HTTP)
|
|
194
|
+
.end method
|
|
195
|
+
|
|
196
|
+
.method public static fetch()V
|
|
197
|
+
# Fetch latest config from remote
|
|
198
|
+
.end method
|
|
199
|
+
|
|
200
|
+
.method public static getString(String key)String
|
|
201
|
+
# Get string value
|
|
202
|
+
.end method
|
|
203
|
+
|
|
204
|
+
.method public static getInt(String key)I
|
|
205
|
+
# Get int value
|
|
206
|
+
.end method
|
|
207
|
+
|
|
208
|
+
.method public static getBoolean(String key)Z
|
|
209
|
+
# Get boolean value
|
|
210
|
+
.end method
|
|
211
|
+
|
|
212
|
+
.method public static isFeatureEnabled(String)Z
|
|
213
|
+
# Check feature flag
|
|
214
|
+
.end method
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 3.3. Integration với AppPreferences
|
|
218
|
+
|
|
219
|
+
**Update AppPreferences để dùng RemoteConfig:**
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
Before:
|
|
223
|
+
const/4 v0, 0x3 # Hardcoded min = 3
|
|
224
|
+
|
|
225
|
+
After:
|
|
226
|
+
invoke-static {"freq_inter_min"}, RemoteConfigHelper;->getInt()I
|
|
227
|
+
move-result v0 # Dynamic min from config
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 🔌 Phase 4: Fetch Strategy
|
|
233
|
+
|
|
234
|
+
### 4.1. When to Fetch?
|
|
235
|
+
|
|
236
|
+
**Strategy A: Application.onCreate()**
|
|
237
|
+
```
|
|
238
|
+
Pros: Early fetch, ready when needed
|
|
239
|
+
Cons: Delay app start
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Strategy B: Background fetch**
|
|
243
|
+
```
|
|
244
|
+
Pros: No blocking
|
|
245
|
+
Cons: First launch uses defaults
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**Strategy C: Lazy fetch**
|
|
249
|
+
```
|
|
250
|
+
Pros: On-demand
|
|
251
|
+
Cons: Delay when showing ad
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Recommended: Hybrid**
|
|
255
|
+
```
|
|
256
|
+
1. Load cached config immediately
|
|
257
|
+
2. Fetch in background
|
|
258
|
+
3. Apply on next launch (or live if safe)
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 4.2. Caching Mechanism
|
|
262
|
+
|
|
263
|
+
**SharedPreferences caching:**
|
|
264
|
+
```
|
|
265
|
+
Keys:
|
|
266
|
+
- remote_config_json: Full JSON string
|
|
267
|
+
- remote_config_timestamp: Last fetch time
|
|
268
|
+
- remote_config_version: Config version
|
|
269
|
+
|
|
270
|
+
Invalidation:
|
|
271
|
+
- TTL: 12-24 hours
|
|
272
|
+
- Force refresh on app update
|
|
273
|
+
- Manual refresh option
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 4.3. Fallback Strategy
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
Priority:
|
|
280
|
+
1. Remote config (if fresh)
|
|
281
|
+
2. Cached config
|
|
282
|
+
3. Assets config (bundled)
|
|
283
|
+
4. Hardcoded defaults
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## ✅ Phase 5: Testing & Rollout
|
|
289
|
+
|
|
290
|
+
### 5.1. Test Scenarios
|
|
291
|
+
|
|
292
|
+
| Test | Expected | Command |
|
|
293
|
+
|------|----------|---------|
|
|
294
|
+
| **First launch (no cached)** | Use assets config | Clear data, launch |
|
|
295
|
+
| **Fetch success** | Use remote values | Normal launch with network |
|
|
296
|
+
| **Fetch fail** | Use cached/assets | Airplane mode |
|
|
297
|
+
| **Config change** | Reflect on next launch | Change remote, relaunch |
|
|
298
|
+
| **Invalid JSON** | Fallback gracefully | Corrupt remote config |
|
|
299
|
+
|
|
300
|
+
### 5.2. Gradual Rollout
|
|
301
|
+
|
|
302
|
+
**Phase 1: Test with dev account**
|
|
303
|
+
- Use test ad IDs
|
|
304
|
+
- Small audience (1%)
|
|
305
|
+
- Monitor crashes
|
|
306
|
+
|
|
307
|
+
**Phase 2: Staging**
|
|
308
|
+
- Real ad IDs
|
|
309
|
+
- 10-20% audience
|
|
310
|
+
- Monitor metrics (impressions, revenue)
|
|
311
|
+
|
|
312
|
+
**Phase 3: Full rollout**
|
|
313
|
+
- 100% audience
|
|
314
|
+
- Monitor continuously
|
|
315
|
+
|
|
316
|
+
### 5.3. Monitoring
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
# Log config values on app start
|
|
320
|
+
adb logcat | grep "RemoteConfig"
|
|
321
|
+
|
|
322
|
+
# Verify fetched values
|
|
323
|
+
adb shell run-as {package} cat /data/data/{package}/shared_prefs/remote_config.xml
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 📋 Implementation Checklist
|
|
329
|
+
|
|
330
|
+
### Setup
|
|
331
|
+
- [ ] Choose config strategy (Firebase/Server/Hybrid)
|
|
332
|
+
- [ ] Design JSON schema
|
|
333
|
+
- [ ] Create RemoteConfigHelper class
|
|
334
|
+
- [ ] Setup fallback config in assets
|
|
335
|
+
|
|
336
|
+
### Firebase (if used)
|
|
337
|
+
- [ ] Add Firebase SDK dependencies
|
|
338
|
+
- [ ] Add google-services.json
|
|
339
|
+
- [ ] Initialize Firebase
|
|
340
|
+
- [ ] Test Remote Config connection
|
|
341
|
+
|
|
342
|
+
### Integration
|
|
343
|
+
- [ ] Update AppPreferences to use RemoteConfig
|
|
344
|
+
- [ ] Replace hardcoded values với config keys
|
|
345
|
+
- [ ] Implement fetch logic
|
|
346
|
+
- [ ] Add caching mechanism
|
|
347
|
+
|
|
348
|
+
### Testing
|
|
349
|
+
- [ ] Test all fallback scenarios
|
|
350
|
+
- [ ] Verify config updates apply
|
|
351
|
+
- [ ] Test with invalid/missing config
|
|
352
|
+
- [ ] Monitor performance impact
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 🔗 Related Resources
|
|
357
|
+
|
|
358
|
+
### Workflows
|
|
359
|
+
- `/smali-ads-flow` - Uses config for frequency
|
|
360
|
+
- `/smali-ads-interstitial` - Uses ad unit IDs
|
|
361
|
+
- `/smali-ads-native` - Uses ad unit IDs
|
|
362
|
+
|
|
363
|
+
### Firebase Docs
|
|
364
|
+
- [Firebase Remote Config](https://firebase.google.com/docs/remote-config)
|
|
365
|
+
- [Android Integration](https://firebase.google.com/docs/remote-config/use-config-android)
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## 💡 Tips & Best Practices
|
|
370
|
+
|
|
371
|
+
1. **Always have fallback**: App phải work khi remote config fail
|
|
372
|
+
2. **Cache aggressively**: Reduce network calls
|
|
373
|
+
3. **Version config**: Track changes, rollback if needed
|
|
374
|
+
4. **Test offline**: Ensure graceful degradation
|
|
375
|
+
5. **Don't fetch too often**: Respect rate limits, battery
|
|
376
|
+
6. **Use feature flags**: Easy enable/disable features
|
|
377
|
+
7. **Monitor impact**: Track config changes vs metrics
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## ⚠️ Important Considerations
|
|
382
|
+
|
|
383
|
+
### Performance
|
|
384
|
+
- Fetch config async, don't block UI
|
|
385
|
+
- Cache effectively to minimize network
|
|
386
|
+
- Consider app size impact (Firebase SDK ~5-10MB)
|
|
387
|
+
|
|
388
|
+
### Security
|
|
389
|
+
- Don't put sensitive data in remote config
|
|
390
|
+
- Validate config values (prevent abuse)
|
|
391
|
+
- Monitor for unexpected changes
|
|
392
|
+
|
|
393
|
+
### User Experience
|
|
394
|
+
- Changes should be non-disruptive
|
|
395
|
+
- Consider showing update notice if major change
|
|
396
|
+
- Test across different Android versions
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
**🎯 Goal**: Balance flexibility với stability. Remote Config là powerful tool nhưng phải implement carefully!
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 📺 Tích hợp Ads Flow vào APK mod (Smali) - Splash → Ads → Onboarding → Home
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Smali Ads Flow Integration
|
|
6
|
+
|
|
7
|
+
> **🎯 Mục tiêu**: Tạo luồng quảng cáo trong APK mod bằng cách hook vào Splash Activity có sẵn.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 📋 Flow Logic Overview
|
|
12
|
+
|
|
13
|
+
### First Launch (Lần đầu)
|
|
14
|
+
```
|
|
15
|
+
Splash → Inter Ad (100%) → Onboarding + Native Ads → Inter Ad (100%) → Home
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Return Visit (Lần 2+)
|
|
19
|
+
```
|
|
20
|
+
Splash → Inter Ad (random mỗi 3-5 lần) → Home
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🎬 Phase 1: Phân Tích Entry Points
|
|
26
|
+
|
|
27
|
+
**Prerequisites**: Đã decompile APK (xem `apk-modifier` skill)
|
|
28
|
+
|
|
29
|
+
### 1.1. Xác định Splash Activity
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Tìm LAUNCHER Activity trong AndroidManifest.xml
|
|
33
|
+
grep -r "android.intent.category.LAUNCHER" AndroidManifest.xml
|
|
34
|
+
|
|
35
|
+
# Kiểm tra có Splash Activity riêng không
|
|
36
|
+
find smali* -name "*Splash*.smali"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Kết quả mong đợi:**
|
|
40
|
+
- **Scenario A**: App có `SplashActivity` riêng
|
|
41
|
+
- **Scenario B**: `MainActivity` là LAUNCHER (không có Splash)
|
|
42
|
+
|
|
43
|
+
### 1.2. Phân tích Navigation Flow
|
|
44
|
+
|
|
45
|
+
**Sử dụng jadx để hiểu logic:**
|
|
46
|
+
```bash
|
|
47
|
+
jadx-gui target.apk
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Cần xác định:**
|
|
51
|
+
- Method chứa navigation logic (ví dụ: `navigateToMain()`, `goHome()`)
|
|
52
|
+
- Delay mechanism (Handler.postDelayed, Timer, etc.)
|
|
53
|
+
- Target activity (MainActivity class name)
|
|
54
|
+
|
|
55
|
+
**Document findings:**
|
|
56
|
+
```
|
|
57
|
+
Current Flow: [Splash/MainActivity] → [Activity?] → [FinalActivity]
|
|
58
|
+
Navigation Method: navigateToMain() / goHome() / etc.
|
|
59
|
+
Target Activity: com.example.app.MainActivity
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 📦 Phase 2: Thiết Kế Components
|
|
65
|
+
|
|
66
|
+
### 2.1. Cấu trúc SDK cần tạo
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
{SDK_DIR}/
|
|
70
|
+
├── config/
|
|
71
|
+
│ └── AppPreferences.smali # Quản lý state & random logic
|
|
72
|
+
└── activities/
|
|
73
|
+
└── OnboardingActivity.smali # Onboarding với Native Ads
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Note**:
|
|
77
|
+
- `{SDK_DIR}` = thư mục SDK bạn chọn (ví dụ: `smali_classes2/com/myads/`)
|
|
78
|
+
- Package name tùy chỉnh theo dự án
|
|
79
|
+
|
|
80
|
+
### 2.2. Config Strategy
|
|
81
|
+
|
|
82
|
+
**Option 1**: JSON config file trong assets
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"ad_ids": {...},
|
|
86
|
+
"frequency": {"min": 3, "max": 5},
|
|
87
|
+
"main_activity": "com.target.app.MainActivity"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Option 2**: Hardcode trong Smali constants
|
|
92
|
+
```smali
|
|
93
|
+
.field private static final INTER_FREQUENCY_MIN:I = 0x3
|
|
94
|
+
.field private static final INTER_FREQUENCY_MAX:I = 0x5
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🔧 Phase 3: Implementation Strategy
|
|
100
|
+
|
|
101
|
+
### 3.1. Component: AppPreferences
|
|
102
|
+
|
|
103
|
+
**Chức năng cần implement:**
|
|
104
|
+
|
|
105
|
+
| Method | Mục đích | Return |
|
|
106
|
+
|--------|----------|--------|
|
|
107
|
+
| `isFirstLaunch()` | Kiểm tra lần đầu mở app | boolean |
|
|
108
|
+
| `setFirstLaunchDone()` | Đánh dấu đã onboarding | void |
|
|
109
|
+
| `incrementOpenCount()` | Tăng counter mỗi lần mở | int |
|
|
110
|
+
| `shouldShowInterAd()` | Random 3-5 lần | boolean |
|
|
111
|
+
|
|
112
|
+
**Storage**: SharedPreferences
|
|
113
|
+
|
|
114
|
+
**Implementation**: Xem chi tiết Smali syntax trong `apk-modifier` skill
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### 3.2. Injection Strategy
|
|
119
|
+
|
|
120
|
+
#### Scenario A: App có SplashActivity
|
|
121
|
+
|
|
122
|
+
**Hook Point 1: onCreate()**
|
|
123
|
+
```
|
|
124
|
+
Location: SplashActivity.smali
|
|
125
|
+
Action: Inject tracking
|
|
126
|
+
→ Call incrementOpenCount()
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Hook Point 2: Navigation Method**
|
|
130
|
+
```
|
|
131
|
+
Location: navigateToMain() / goHome() / etc.
|
|
132
|
+
Action: Inject flow logic
|
|
133
|
+
→ if isFirstLaunch() → go to Onboarding
|
|
134
|
+
→ else if shouldShowInterAd() → show Inter
|
|
135
|
+
→ else → go to MainActivity
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
#### Scenario B: MainActivity là LAUNCHER
|
|
141
|
+
|
|
142
|
+
**Hook Point: onCreate()**
|
|
143
|
+
```
|
|
144
|
+
Location: MainActivity.smali
|
|
145
|
+
Action 1: Tạo method mới checkAdsFlow()
|
|
146
|
+
Action 2: Inject call vào đầu onCreate()
|
|
147
|
+
→ Call checkAdsFlow()
|
|
148
|
+
→ Logic tương tự Scenario A
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### 3.3. Component: OnboardingActivity
|
|
154
|
+
|
|
155
|
+
**Chức năng:**
|
|
156
|
+
- ViewPager/HorizontalScrollView với N slides
|
|
157
|
+
- Native Ad container (giữa hoặc cuối slides)
|
|
158
|
+
- Next/Skip buttons
|
|
159
|
+
- Khi complete → call `setFirstLaunchDone()`
|
|
160
|
+
|
|
161
|
+
**Navigation:**
|
|
162
|
+
```
|
|
163
|
+
OnboardingActivity → [Show Inter Ad?] → MainActivity
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 🔌 Phase 4: Integration
|
|
169
|
+
|
|
170
|
+
### 4.1. AndroidManifest Changes
|
|
171
|
+
|
|
172
|
+
**Thêm permissions:**
|
|
173
|
+
```xml
|
|
174
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
175
|
+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Thêm AdMob App ID:**
|
|
179
|
+
```xml
|
|
180
|
+
<meta-data
|
|
181
|
+
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
|
182
|
+
android:value="ca-app-pub-{YOUR_PUBLISHER_ID}~{APP_ID}"/>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Đăng ký OnboardingActivity:**
|
|
186
|
+
```xml
|
|
187
|
+
<activity
|
|
188
|
+
android:name="{YOUR_PACKAGE}.activities.OnboardingActivity"
|
|
189
|
+
android:exported="false"
|
|
190
|
+
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"/>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**⚠️ Quan trọng**: KHÔNG thay đổi LAUNCHER activity
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### 4.2. Copy Dependencies
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Tùy project structure, có thể là smali, smali_classes2, etc.
|
|
201
|
+
|
|
202
|
+
# Copy AdMob libraries (nếu chưa có)
|
|
203
|
+
# Thường nằm trong com/google/android/gms/ads/
|
|
204
|
+
|
|
205
|
+
# Verify method count
|
|
206
|
+
find smali* -name "*.smali" | wc -l # Phải < 60,000
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### 4.3. Reference Validation
|
|
212
|
+
|
|
213
|
+
**Kiểm tra injection đúng:**
|
|
214
|
+
```bash
|
|
215
|
+
# Tìm tất cả reference đến AppPreferences
|
|
216
|
+
grep -r "AppPreferences" smali*/
|
|
217
|
+
|
|
218
|
+
# Tìm reference đến OnboardingActivity
|
|
219
|
+
grep -r "OnboardingActivity" smali*/
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Expected**: Thấy reference trong Splash/MainActivity
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 📺 Phase 5: Ads Implementation
|
|
227
|
+
|
|
228
|
+
> **Tách workflow riêng**: `/smali-ads-interstitial`, `/smali-ads-native`
|
|
229
|
+
|
|
230
|
+
**Tổng quan:**
|
|
231
|
+
1. **Interstitial Ads**
|
|
232
|
+
- Load khi Splash onCreate()
|
|
233
|
+
- Show sau Splash, sau Onboarding
|
|
234
|
+
- Show random theo `shouldShowInterAd()`
|
|
235
|
+
|
|
236
|
+
2. **Native Ads**
|
|
237
|
+
- Load trong OnboardingActivity
|
|
238
|
+
- Display trong ad container
|
|
239
|
+
- Cleanup khi destroy
|
|
240
|
+
|
|
241
|
+
**Chi tiết**: Xem workflows riêng
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## ✅ Phase 6: Build & Test
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### 6.2. Test Scenarios
|
|
250
|
+
|
|
251
|
+
| Scenario | Expected Behavior | Verification |
|
|
252
|
+
|----------|-------------------|--------------|
|
|
253
|
+
| **First Launch** | Splash → [Inter?] → Onboarding → [Inter?] → Home | Clear app data, launch |
|
|
254
|
+
| **2nd Launch** | Splash → Home (no ads) | Launch again |
|
|
255
|
+
| **3rd-5th Random** | Splash → [Inter random] → Home | Launch 10+ times, observe pattern |
|
|
256
|
+
| **Onboarding Skip** | Skip button works, navigate correctly | Test skip button |
|
|
257
|
+
|
|
258
|
+
### 6.3. Debug Commands
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# Monitor flow events
|
|
262
|
+
adb logcat | grep -E "Preference|Onboarding|Navigation"
|
|
263
|
+
|
|
264
|
+
# Check SharedPreferences state
|
|
265
|
+
adb shell run-as {package} cat /data/data/{package}/shared_prefs/*.xml
|
|
266
|
+
|
|
267
|
+
# Extract & verify counter
|
|
268
|
+
# Should see: open_count, next_ad_count, first_launch values
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## 📋 Implementation Checklist
|
|
274
|
+
|
|
275
|
+
### Pre-Implementation
|
|
276
|
+
- [ ] APK đã decompile xong
|
|
277
|
+
- [ ] Xác định Splash/MainActivity và navigation method
|
|
278
|
+
- [ ] Document flow hiện tại
|
|
279
|
+
- [ ] Backup APK gốc
|
|
280
|
+
|
|
281
|
+
### Core Components
|
|
282
|
+
- [ ] Tạo AppPreferences với 4 methods
|
|
283
|
+
- [ ] Implement random logic (3-5 range)
|
|
284
|
+
- [ ] Tạo OnboardingActivity skeleton
|
|
285
|
+
- [ ] Test SharedPreferences đọc/ghi đúng
|
|
286
|
+
|
|
287
|
+
### Injection
|
|
288
|
+
- [ ] Hook vào onCreate() - tracking
|
|
289
|
+
- [ ] Hook vào navigation method - flow logic
|
|
290
|
+
- [ ] Test first launch flow
|
|
291
|
+
- [ ] Test return visit flow
|
|
292
|
+
|
|
293
|
+
### Integration
|
|
294
|
+
- [ ] Update AndroidManifest
|
|
295
|
+
- [ ] Copy dependencies (check method count)
|
|
296
|
+
- [ ] Validate all references
|
|
297
|
+
- [ ] Build thành công (no errors)
|
|
298
|
+
|
|
299
|
+
### Testing
|
|
300
|
+
- [ ] First launch: đúng flow
|
|
301
|
+
- [ ] Return visit: random đúng (test 10+ lần)
|
|
302
|
+
- [ ] Onboarding: skip/next works
|
|
303
|
+
- [ ] No crashes, no ANR
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 🔗 Related Resources
|
|
308
|
+
|
|
309
|
+
### Workflows
|
|
310
|
+
- `/smali-ads-interstitial` - Interstitial Ads implementation
|
|
311
|
+
- `/smali-ads-native` - Native Ads implementation
|
|
312
|
+
- `/smali-ads-config` - Remote Config cho Ad settings
|
|
313
|
+
|
|
314
|
+
### Skills & Docs
|
|
315
|
+
- **Skill**: `apk-modifier` - Smali techniques & examples
|
|
316
|
+
- **Cheatsheet**: `SMALI_CHEATSHEET.md` - Syntax reference
|
|
317
|
+
- **Tool**: jadx-gui - Decompile để đọc logic
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 💡 Tips & Best Practices
|
|
322
|
+
|
|
323
|
+
1. **Package Naming**: Chọn tên package phù hợp với app để tránh confusion
|
|
324
|
+
2. **Method Count**: Monitor liên tục, phân bổ sang smali_classes* nếu cần
|
|
325
|
+
3. **Testing**: Test với nhiều scenarios, đặc biệt random logic
|
|
326
|
+
4. **Logging**: Thêm Log.d() trong Smali để debug flow
|
|
327
|
+
5. **Backup**: Luôn giữ backup trước mỗi thay đổi lớn
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
**⚠️ Note**: Workflow này chỉ tập trung vào **FLOW LOGIC**. Chi tiết Ads implementation xem workflows riêng.
|