请求Android Dynamic Asset Delivery分步实现方案:添加3个资源包
Got it, let's walk through this step by step—setting up three different Asset Packs for Dynamic Asset Delivery isn't as tricky as it seems once you break it down. I'll cover everything from project setup to testing, so you can follow along easily.
1. Confirm Your Project Meets the Requirements
First, make sure your project is ready for Dynamic Asset Delivery:
- You're using Android Gradle Plugin (AGP) 4.0 or higher (check this in your project-level
build.gradlefile) - Your app's
minSdkVersionis set to 21 or higher - You're building an Android App Bundle (AAB) (not just APKs)—this is required for dynamic delivery to work with Google Play.
2. Create Your Asset Packs (Repeat for All 3)
Each Asset Pack is a separate module in your Android Studio project. Let's create the first one, then you can duplicate the process for the other two:
- Open Android Studio, go to File > New > New Module
- In the module template list, select Asset Pack and click Next
- Fill in the details:
- Asset pack name: Use lowercase letters and underscores (e.g.,
asset_pack_levels,asset_pack_sounds,asset_pack_textures)—no uppercase or special characters allowed - Application ID: This should match your main app's application ID (e.g.,
com.yourcompany.yourapp) - Delivery type: Choose one of the three options (I'll explain each below)
- Asset pack name: Use lowercase letters and underscores (e.g.,
- Click Finish to create the module.
Quick Breakdown of Delivery Types
Pick a unique type for each of your three packs based on your needs:
- Install-time: Pack installs alongside your main app. Resources are accessible like your app's native resources, and users can't delete it. Great for critical, must-have assets.
- Fast-follow: Pack downloads automatically in the background right after the main app installs. Users can see download progress in your app. Perfect for frequently used but non-critical assets.
- On-demand: Pack only downloads when the user triggers it (e.g., tapping a "Download Extra Levels" button). Ideal for large, rarely used assets.
3. Configure Each Asset Pack
Once your modules are created, configure each one:
Add Assets to the Pack
Open the Asset Pack module's directory, and add your resources to either:
src/main/assets/: For raw assets (like JSON files, audio clips, or custom textures)src/main/res/: For standard Android resources (like drawables, layouts, or strings)
Update the Pack's Build.Gradle
Open the Asset Pack module's build.gradle file and verify (or adjust) these settings:
plugins { id 'com.android.asset-pack' } android { namespace "com.yourcompany.yourapp.asset_pack_levels" // Match your app's namespace + pack name compileSdk 34 // Use the same compileSdk as your main app defaultConfig { minSdk 21 // Match your main app's minSdk targetSdk 34 // Match your main app's targetSdk } assetPack { deliveryType = "install-time" // Replace with "fast-follow" or "on-demand" for other packs // Optional: Set download priority for fast-follow/on-demand packs (1 = highest priority) // downloadPriority = 1 } }
4. Link Asset Packs to Your Main App
Now, tell your main app about the three Asset Packs:
- Open your main app's
build.gradlefile - Add the
dynamicFeaturesproperty inside theandroidblock, listing all three Asset Pack modules:
android { // ... other settings // List all your Asset Pack modules here dynamicFeatures = [":asset_pack_levels", ":asset_pack_sounds", ":asset_pack_textures"] // Make sure App Bundle splitting is enabled (this is default in newer AGP versions) bundle { language { enableSplit = true } density { enableSplit = true } abi { enableSplit = true } } }
5. Access Assets in Your App
The way you access resources depends on the Asset Pack's delivery type:
For Install-Time Packs
These resources are merged with your main app's resources, so you can access them just like native assets:
// Access a drawable from an install-time pack imageView.setImageResource(R.drawable.level_banner) // Access a raw asset from an install-time pack val inputStream = assets.open("level_data.json") val levelData = inputStream.bufferedReader().readText()
For Fast-Follow & On-Demand Packs
You need to request the pack download first, then access the resources once it's available. Here's a Kotlin example:
Step 1: Initialize the Asset Pack Manager
import com.google.android.play.core.assetpacks.AssetPackManager import com.google.android.play.core.assetpacks.AssetPackManagerFactory import com.google.android.play.core.assetpacks.AssetPackRequest import com.google.android.play.core.assetpacks.model.AssetPackStatus class MainActivity : AppCompatActivity() { private lateinit var assetPackManager: AssetPackManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Initialize the Asset Pack Manager assetPackManager = AssetPackManagerFactory.getInstance(this) } }
Step 2: Request an On-Demand Pack Download
// Call this when the user triggers a download (e.g., a button click) fun downloadOnDemandPack() { val packName = "asset_pack_textures" // Replace with your pack's name val request = AssetPackRequest.newBuilder(packName).build() assetPackManager.fetch(request).addOnCompleteListener { task -> if (task.isSuccessful) { // Listen for download status updates assetPackManager.registerListener { state -> when (state.status()) { AssetPackStatus.DOWNLOADING -> { // Calculate and display progress val progress = (state.bytesDownloaded() * 100 / state.totalBytesToDownload()).toInt() progressBar.progress = progress } AssetPackStatus.COMPLETED -> { // Download finished—access the assets accessOnDemandAssets(packName) } AssetPackStatus.FAILED -> { // Handle download failure (e.g., show an error message) Toast.makeText(this, "Download failed", Toast.LENGTH_SHORT).show() } } } } else { Toast.makeText(this, "Could not start download", Toast.LENGTH_SHORT).show() } } }
Step 3: Access Downloaded Assets
private fun accessOnDemandAssets(packName: String) { // Access a raw asset from the pack val assetManager = createPackageContext(packageName, 0).assets val textureStream = assetManager.open("$packName/hd_texture.png") val bitmap = BitmapFactory.decodeStream(textureStream) textureImageView.setImageBitmap(bitmap) // Access a drawable from the pack's res directory val drawableResId = resources.getIdentifier("hd_icon", "drawable", "$packageName.$packName") iconImageView.setImageResource(drawableResId) }
6. Test Your Implementation
Testing dynamic delivery requires a bit more setup than regular APK testing:
- Build an App Bundle: Go to Build > Build Bundle(s) / APK(s) > Build Bundle(s) to generate your
.aabfile. - Test with Google Play Internal Testing: Upload the AAB to Google Play's Internal Testing track, then install the app via the Play Store. This is the most reliable way to test fast-follow and on-demand packs, since local testing has limitations.
- Local Testing for Install-Time Packs: If you just want to test install-time packs, generate a universal APK (Build > Build Bundle(s) / APK(s) > Build APK(s))—this will include all install-time assets directly in the APK.
Common Pitfalls to Avoid
- Pack Name Errors: Always use lowercase and underscores for pack names—capital letters will cause build failures.
- Incorrect Delivery Type: Make sure you're accessing assets correctly based on the pack's delivery type (e.g., don't try to access an on-demand pack's assets before it's downloaded).
- AGP Version Issues: If you're using an older AGP version, update it to 4.0+ to avoid compatibility problems.
内容的提问来源于stack exchange,提问作者Mahadheer Muhammed

