React Native中如何使用Play Asset Delivery分离视频资源
在React Native中使用Play Asset Delivery分离并调用视频资源
一、配置Android端Play Asset Delivery结构
Play Asset Delivery是Android专属功能,需先在Android项目中配置资源结构和依赖:
- 在
app/src/main下创建assets目录,按交付类型创建子目录(如on-demand/videos),将视频文件放入对应路径(例:assets/on-demand/videos/demo.mp4) - 修改
app/build.gradle,添加Asset Delivery依赖和资产包声明:
android { // ... 其他配置 assetPacks = [":on-demand-videos"] // 资产包名称,需与后续模块对应 } dependencies { // ... 其他依赖 implementation 'com.google.android.play:asset-delivery:2.2.0' }
- 在项目根目录创建资产包模块(如
on-demand-videos),其build.gradle配置如下:
plugins { id 'com.android.asset-pack' } assetPack { packName = "on-demand-videos" // 与app/build.gradle中的assetPacks对应 dynamicDelivery { deliveryType = "on-demand" // 可选值:install-time/fast-follow/on-demand } }
二、编写React Native原生桥接模块
React Native无原生支持Play Asset Delivery,需自定义原生模块实现资源路径获取:
- 创建Kotlin模块类
PlayAssetDeliveryModule.kt:
package com.your_app_package_name; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Promise; import com.google.android.play.core.assetpacks.AssetPackManager; import com.google.android.play.core.assetpacks.AssetPackManagerFactory; import com.google.android.play.core.assetpacks.AssetPackState; import com.google.android.play.core.assetpacks.AssetPackStateUpdateListener; import com.google.android.play.core.assetpacks.model.AssetPackStatus; import java.io.File; import kotlin.collections.Lists; class PlayAssetDeliveryModule extends ReactContextBaseJavaModule { private AssetPackManager assetPackManager; PlayAssetDeliveryModule(ReactApplicationContext context) { super(context); assetPackManager = AssetPackManagerFactory.create(context); } @Override public String getName() { return "PlayAssetDelivery"; } @ReactMethod public void getVideoPath(String videoName, Promise promise) { String packName = "on-demand-videos"; // 检查资产包是否已下载完成 assetPackManager.getPackStates(Lists.listOf(packName)).addOnCompleteListener(task -> { if (task.isSuccessful()) { AssetPackState state = task.getResult().get(packName); if (state != null && state.status() == AssetPackStatus.COMPLETED) { String assetPath = new File(assetPackManager.getAssetsPath(packName), "videos/" + videoName).getAbsolutePath(); promise.resolve(assetPath); } else { // 触发资产包下载并监听状态 assetPackManager.fetch(Lists.listOf(packName)); assetPackManager.registerListener(new AssetPackStateUpdateListener() { @Override public void onStateUpdate(AssetPackState updateState) { if (updateState.packName().equals(packName)) { if (updateState.status() == AssetPackStatus.COMPLETED) { String assetPath = new File(assetPackManager.getAssetsPath(packName), "videos/" + videoName).getAbsolutePath(); promise.resolve(assetPath); assetPackManager.unregisterListener(this); } else if (updateState.status() == AssetPackStatus.FAILED) { promise.reject("DOWNLOAD_FAILED", "Failed to download asset pack"); assetPackManager.unregisterListener(this); } } } }); } } else { promise.reject("STATE_CHECK_ERROR", "Failed to check asset pack state"); } }); } }
- 创建包注册类
PlayAssetDeliveryPackage.kt:
package com.your_app_package_name; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; import java.util.List; class PlayAssetDeliveryPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new PlayAssetDeliveryModule(reactContext)); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
- 在
MainApplication.kt中注册该包:
override fun getPackages(): List<ReactPackage> { return PackageList(this).packages.apply { add(PlayAssetDeliveryPackage()) } }
三、在JavaScript中调用原生模块获取并播放视频
通过NativeModules调用原生方法获取视频本地路径,再用react-native-video播放:
import { NativeModules, Platform } from 'react-native'; import Video from 'react-native-video'; import { useState } from 'react'; const { PlayAssetDelivery } = NativeModules; const [videoSource, setVideoSource] = useState(null); // 获取并播放视频的异步函数 const loadAndPlayVideo = async (videoFileName) => { if (Platform.OS !== 'android') { console.warn('Play Asset Delivery is Android-only'); return; } try { const localPath = await PlayAssetDelivery.getVideoPath(videoFileName); setVideoSource({ uri: `file://${localPath}` }); } catch (err) { console.error('Failed to load video:', err); } }; // 使用示例:调用loadAndPlayVideo('demo.mp4')
渲染Video组件:
{videoSource && ( <Video source={videoSource} style={{ width: '100%', height: 300 }} controls={true} /> )}
四、打包上传至Google Play
- 生成App Bundle(
.aab)而非APK,Play Asset Delivery仅支持Bundle格式 - 在Google Play Console中确认资产包的交付类型配置与本地代码一致
内容的提问来源于stack exchange,提问作者Joe199382
相关产品推荐
相关产品推荐

