# 下载地址
- 下载 SDK:MachbirdSDK-Open-2019_09_20_11_37_46.unitypackage
- 将 unitypackage 文件导入到 Unity 里
# Android 项目配置
设置Build System为"Gradle"
Assets/Plugins/Android/AndroidManifest.xml文件里添加配置参数,格式如下所示,具体参数值由运营提供<application> ... <!--Machbird SDK App Key--> <meta-data android:name="io.MachBird.sdk.x.AppKey" android:value="xxxxxxxxxxx" /> <!--Adjust Token--> <meta-data android:name="com.adjustX.sdk.appToken" android:value="xxxxxxxxxxx" /> <!--Flurry Key--> <meta-data android:name="FLURRY_API_KEY" android:value="xxxxxxxxxxxxx" /> <!--IronSource App Key--> <meta-data android:name="com.ironsource.sdk.appKey" android:value="xxxxxxxx" /> <!--Admob Application ID--> <meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="xxxxxxxxxxx" /> ... </application>Admob Android 的配置 ID 如果不加会启动崩溃,可先用下面的测试配置
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-3940256099942544~3347511713" />启用 MultiDex
第一步,在
mainTemplate.gradle文件里加上multiDexEndabled true,如下所示defaultConfig { minSdkVersion **MINSDKVERSION** targetSdkVersion **TARGETSDKVERSION** applicationId '**APPLICATIONID**' ndk { abiFilters **ABIFILTERS** } versionCode **VERSIONCODE** versionName '**VERSIONNAME**' multiDexEnabled true }第二步,在
AndroidManifest.xml里声明 Application 使用android.support.multidex.MultiDexApplication,示例如下<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application android:name="android.support.multidex.MultiDexApplication" > ... </application> </manifest>
For Android's method of enabling MultiDex, please refer to the official Android documentation: https://developer.android.com/studio/build/multidex?hl=en
# iOS 项目配置
iOS 项目在Info->Custom iOS Target Properties里增加以下配置,具体参数值由运营提供
io.MachBird.sdk.x.AppKey=xxxxxxxxxxx adjust_token=xxxxxxxxx FLURRY_API_KEY_IOS=xxxxxxxxx com.ironsource.sdk.appKey=xxxxxxx GADApplicationIdentifier=xxxxxxxAdmob iOS 的测试 ID
<key>GADApplicationIdentifier</key> <string>ca-app-pub-3940256099942544~1458002511</string>
如下图所示

- XCode 工程在编译时,需要关闭 Bitcode
# 初始化
在第一个场景的 Awake 方法里调用 SDK 的初始化 API
MachbirdSDK.Init();进入游戏主界面时调用 API
MachbirdSDK.LogMainPageShow();
# 接入可能遇到的问题
接入 Machbird SDK 后,在 Android 6.0 以上设备启动游戏时出现权限申请弹窗,在接入 SDK 之前没有
原因:Machbird SDK 有一些权限是游戏之前没有的,而 Unity 默认情况会在启动时自动检查有哪些权限没有获得授权,会依次主动申请这些权限,而触发系统弹窗
解决办法:在
Assets/Plugins/Android/AndroidManifest.xml里加上以下配置来关闭自动申请权限这一行为。<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true
# 广告 API
# 1. 支持的广告类型
- 插屏广告
- 激励视频广告
- 横幅广告(320*50)
示例工程:MachbirdAdDemo.zip
# 2. 插屏广告
注册广告事件(广告请求成功、请求失败、展示、点击、关闭)
/** * 设置加载插屏广告的回调。 * @param onSuccess 成功回调。 * @param onFail 失败回调。 */ MachbirdAdManager.SetLoadInterstitialAdListener( () => { Debug.Log("Load Interstitial AD successfully"); }, msg => { Debug.Log("Load Interstitial AD failed," + msg); });/** * 设置插屏广告事件的回调。 * @param onAdShowed 广告展示回调。 * @param onAdClicked 广告点击回调。 * @param onAdClosed 广告关闭回调。 */ MachbirdAdManager.SetShowInterstitialAdListener( (() => { Debug.Log(" Interstitial Ad impression successfully"); }), (() => { Debug.Log(" Interstitial Ad was clicked"); }), (() => { Debug.Log(" Interstitial Ad was closed"); }));请求插屏广告
MachbirdAdManager.LoadInterstitialAd();检查广告可用性
MachbirdAdManager.IsInterstitialAdReady();展示插屏广告
if (MachbirdAdManager.IsRewardAdReady()){ MachbirdAdManager.ShowInterstitialAd(string trigger); }
# 3. 激励视频广告
注册广告事件(广告请求成功、请求失败、展示、点击、关闭、奖励)
/** * 设置请求激励视频广告的回调。 * @param onSuccess 成功回调。 * @param onFail 失败回调。 */ MachbirdAdManager.SetLoadRewardAdListener( () => { Debug.Log("Load Reward AD successfully"); }, msg => { Debug.Log("Load Reward AD failed," + msg); });/** * 设置激励视频广告事件的回调。 * * @param onAdShowed 广告展示回调。 * @param onAdClicked 广告点击回调。 * @param onAdClosed 广告关闭回调。 * @param onAdReward 奖励回调。 */ MachbirdAdManager.SetShowInterstitialAdListener( (() => { Debug.Log(" Reward Ad impression successfully"); }), (() => { Debug.Log(" Reward Ad was clicked"); }), (() => { Debug.Log(" Reward Ad was closed"); }), (() => { Debug.Log(" Reward Ad got Reward"); }));请求激励视频广告
MachbirdAdManager.LoadRewardAd();检查广告可用性
MachbirdAdManager.IsRewardAdReady();展示激励视频广告
if (MachbirdAdManager.IsRewardAdReady()){ MachbirdAdManager.ShowRewardAd(string trigger); }
# 4. 横幅广告
注册广告事件(广告请求成功、请求失败、展示、点击)
/** * 设置请求Banner广告的回调。 * @param onSuccess 成功回调。 * @param onFail 失败回调。 */ MachbirdAdManager.SetLoadBannerAdListener( () => { Debug.Log("Load Banner AD successfully"); }, msg => { Debug.Log("Load Banner AD failed," + msg); } );/** * 设置Banner广告事件的回调。 * @param onAdImpressed广告展示回调。 * @param onAdClicked广告点击回调。 */ MachbirdAdManager.SetShowBannerAdListener( (() => { Debug.Log(" Banner Ad was show"); }), (() => { Debug.Log(" Banner Ad got clicked"); }));请求横幅广告
MachbirdAdManager.LoadBannerAd();检查广告可用性
MachbirdAdManager.IsBannerAdReady();展示横幅广告
MachbirdAdManager.ShowBannerAd(BannerAdPosition bannerAdPosition,string trigger);- BannerAdPosition.TOP:Banner 广告将位于屏幕的顶部中心
- BannerAdPosition.BOTTOM:Banner 广告横幅将位于屏幕的底部中
隐藏横幅广告
MachbirdAdManager.HideBannerAd();
# 5. 接入可能遇到的问题
- Banner 广告展示位置 Banner 广告目前只支持在屏幕的最底部和最顶部显示,请预留 50dp 高度给广告。
- 广告请求失败 请确认是否在清单文件中添加了广告配置
- 请在合理的时机调用广告请求方法,比如:关卡结束、页面切换等
- 有任何集成技术问题都可以联系我们。
# 6. 错误码说明
| 错误码 | 说明 |
|---|---|
| 200 | 请求成功 |
| 1002 | 网络错误 |
| 1003 | 未知错误 |
| 1004 | 非法参数 |
| 1005 | 广告配置配置错误 |
| 1007 | 请求超时 |
| 1008 | 广告无填充 |
| 1009 | 广告请求太频繁 |
| 1012 | 错误的广告类型 |
| 1026 | 广告没有初始化 |
| 1040 | 广告初始化错误 |
# 数据统计
# 1. 激活和 DAU 计算
LogMainPageShow
【调用时机】进入游戏的主界面时,主动调用。
【方法】
/**
* 记录游戏进入主界面
*/
MachbirdSDK.LogMainPageShow()
# 2. 任务和进度
【特定参数说明】
| 传固定值的参数名称 | 参数的枚举值 | 枚举值的说明 |
|---|---|---|
| questType | QuestType.MAIN | 主线任务,默认值。 |
| QuestType.NEW | 新手任务。 | Content |
| QuestType.SUB | 支线任务。 | Content |
LogQuestBegin
【调用时机】关卡类游戏,在进入关卡时,由接入方手动调用。
【方法 1】
/**
* 记录游戏任务的开始
*
* @param questIndex 任务/关卡/副本的索引号。
*/
MachbirdSDK.LogQuestBegin(int questIndex)
【方法 2】
/**
* 记录游戏任务的开始(全部参数)
*
* @param questIndex 任务/关卡/副本的索引号。
* @param questType 当前的任务/关卡/副本的类型;例如主线任务、新手任务、支线任务。
* @param questId 任务/关卡/副本的名称或编号。
* @param questName 游戏任务名称。
* @param progress 关卡内的进度。
* @param times 次数。
*/
MachbirdSDK.LogQuestBegin(int questIndex, QuestType questType, string questId, string questName, int progress, int times)
LogQuestCompleted
【调用时机】关卡类游戏,在关卡成功完成时,由接入方手动调用。
【方法 1】
/**
* 记录游戏任务的完成
*
* @param questIndex 任务/关卡/副本的索引号。
*/
MachbirdSDK.LogQuestCompleted(int questIndex)
【方法 2】
/**
* 记录游戏任务的完成(全部参数)
*
* @param questIndex 任务/关卡/副本的索引号。
* @param questType 当前的任务/关卡/副本的类型;例如主线任务、新手任务、支线任务。
* @param questId 任务/关卡/副本的名称或编号。
* @param questName 游戏任务名称。
* @param progress 关卡内的进度。
* @param times 次数。
*/
MachbirdSDK.LogQuestCompleted(int questIndex, QuestType questType, string questId, string questName, int progress, int times)
LogQuestFailed
【调用时机】关卡类游戏,在关卡闯关失败时,由接入方手动调用。
【方法 1】
/**
* 记录游戏任务的失败
*
* @param questIndex 任务/关卡/副本的索引号。
*/
MachbirdSDK.LogQuestFailed(int questIndex)
【方法 2】
/**
* 记录游戏任务的失败(全部参数)
*
* @param questIndex 任务/关卡/副本的索引号。
* @param questType 当前的任务/关卡/副本的类型;例如主线任务、新手任务、支线任务。
* @param questId 任务/关卡/副本的名称或编号。
* @param questName 游戏任务名称。
* @param progress 关卡内的进度。
* @param times 次数。
*/
MachbirdSDK.LogQuestFailed(int questIndex, QuestType questType, string questId, string questName, int progress, int times)
# 3. 虚拟交易
LogBuy
【调用时机】当用虚拟货币成功购买某游戏物品时,由接入方手动调用。
【方法 1】
/**
* 记录游戏购买
*
* @param itemName 游戏内购买的虚拟物品的名称。
*/
MachbirdSDK.LogBuy(string itemName)
【方法 2】
/**
* 记录游戏购买
*
* @param itemName 游戏内购买的虚拟物品的名称。
* @param itemNum 购买的数量。
* @param itemTotalPrice 购买的总价。
*/
MachbirdSDK.LogBuy(string itemName, long itemNum, double itemTotalPrice)
LogSell
【调用时机】当用成功出售某游戏物品,获取到虚拟货币时,由接入方手动调用。
【方法】
/**
* 记录游戏出售
*
* @param itemName 游戏内出售的虚拟物品的名称。
* @param itemNum 出售的数量。
* @param itemTotalPrice 出售的总价。
*/
MachbirdSDK.LogSell(string itemName, long itemNum, double itemTotalPrice)
# 4. IAP
LogPaySuccess
【调用时机】用户使用真实货币充值成功后,由接入方手动调用。
【方法】
/**
* 记录游戏充值成功
*
* @param transactionId 交易的流水号。
* @param paymentType 支付类型;例如支付宝、银联、微信等,若为系统赠送,则传free。
* @param currencyType 货币类型;例如CNY人民币,USD美金等。
* @param realCoinNum 支付的真实货币的金额。
* @param virtualCoinNum 充值获得的游戏货币的数量。
* @param iapName 游戏内购买道具的名称。
* @param iapNum 游戏内购买道具的数量。
*/
MachbirdSDK.LogPaySuccess(string transactionId, string paymentType, string currencyType, double realCoinNum, long virtualCoinNum, string iapName, long iapNum)
LogSubscribe
【调用时机】用户订阅成功后,由接入方手动调用。
【方法】
/**
* 记录游戏订阅
*
* @param subscriptionId 订阅的流水号。
* @param paymentType 支付类型;例如支付宝、银联、微信等,若为系统赠送,则传free。
* @param currencyType 货币类型;例如CNY人民币,USD美金等。
* @param realCoinNum 支付的真实货币的金额。
*/
MachbirdSDK.LogSubscribe(string subscriptionId, string paymentType, string currencyType, double realCoinNum)
# 5. 广告统计
【重要参数的说明】
trigger:**代表广告的触发场景,主属性,不允许为空。**
用于描述广告触发时的页面信息,不管广告的产生来源于哪个页面,比如首页请求的广告,trigger 值就可以传 main_page。
# 插屏广告统计
OnInterstitialRequest
【调用时机】当发生插屏广告的请求时,由接入方手动调用。
【方法】
/**
* 记录插屏广告请求。
*
* @param trigger 插屏广告的触发场景,主属性。
* @param isReady 是否有缓存。
*/
MachbirdSDK.OnInterstitialRequest(string trigger, bool isReady)
# 激励视频广告统计
激励视频广告的接入说明:
目前我们的游戏是依靠商业化广告做变现,因此游戏中的广告表现对我们来说十分重要。而且广告中,激励视频的广告价值最高,需要重点关注。
为了弄清激励视频广告的表现,需要针对广告做清楚的打点统计。
1、标记激励视频广告的来源
首先我们需要使用 Trigger,来标记是从什么位置来的激励视频广告。这样我们可以观察哪些位置的广告表现差,可以有目标的去优化。
2、标记广告的状态
在我们明确了激励视频广告的位置后,需要观察为什么有些位置的视频广告表现较差。
因此我们要使用 status 来记录激励视频广告的不同状态,查找为什么表现差的原因,这样可以针对激励视频的具体环节去优化。
首先激励视频广告的产生的流程顺序如下:
1、激励视频场景触发后调用广告(ready)
2、调用请求发出后广告下载缓存完成/无下载缓存(ready=1/0)
步骤 1、2 请调用 OnRewardRequest()
3、有缓存时用户点击看视频的按钮(open)
步骤 3 请调用 OnRewardOpen()
4、激励视频广告开始播放展示(content_show)
此步骤 SDK 内部自动打点
5、点击激励视频广告的展示出内容 (content_click)
此步骤 SDK 内部自动打点
6、视频广告播放完成(rewarded)
此步骤 SDK 内部自动打点
此时我们可以根据以上 6 个步骤的数据表现,去顺势优化比较大的环节。
因此为保证的接入质量,我们务必需要根据以上的逻辑去区分标记我们的广告行为。
OnRewardRequest
【调用时机】当发生激励视频广告的请求时,由接入方手动调用。
【方法】
/**
* 记录激励视频广告的请求。
*
* @param trigger 激励视频广告的触发场景,主属性。
* @param isReady 是否有缓存。
*/
MachbirdSDK.OnRewardRequest(string trigger, bool isReady)
OnRewardOpen
【调用时机】触发激励视频广告的打开按钮时,由接入方手动调用。
【方法】
/**
* 记录激励视频广告的打开。
*
* @param trigger 激励视频广告的触发场景,主属性。
*/
MachbirdSDK.OnRewardOpen(String trigger)
# 横幅广告统计
OnBannerRequest
【调用时机】当发生横幅广告的请求时,由接入方手动调用。
【方法】
/**
* 记录横幅广告请求。
*
* @param trigger 横幅广告的触发场景,主属性。
* @param isReady 是否有缓存。
*/
MachbirdSDK.OnBannerRequest(string trigger, bool isReady)
# 6. 账号行为
LogRegister
【调用时机】当用户注册成功后,由接入方手动调用。
【方法】
/**
* 记录账户注册
*
* @param accountId 账户id,唯一标识一个账户。
* @param accountType 账户类型,例如自有账户、第三方登录账户等。
* @param age 注册时获取到的用户年龄。
* @param gender 注册时获取到的用户性别。
*/
MachbirdSDK.LogRegister(string accountId, string accountType, int age, Gender gender)
LogLogin
【调用时机】当用户登录成功后,由接入方手动调用。
【方法】
/**
* 记录账户登录
*
* @param accountId 账户id,唯一标识一个账户。
* @param accountLevel 账户等级。
*/
MachbirdSDK.LogLogin(string accountId, string accountLevel)
# 7. 自定义事件
LogCustomEvent
【调用时机】记录自定义事件,用于游戏 BI 平台的打点分析功能,由接入方手动调用。
【方法】
/**
* 记录自定义事件
*
* @param name 自定义事件的名称。
* @param customParamsJson 自定义的参数Key和Value,传Json格式的字符串,根节点必须是JSON对象不能是JSON数组,不支持嵌套JSON,总长度超过10240字节进行预警。
*/
MachbirdSDK.LogCustomEvent(string name, string customParamsJson)
# 8. Adjust 打点
LogByAdjust
【调用时机】
【方法】
/**
* 通过Adjust打点
*
*@param eventToken 事件Token,相当于事件ID,由运营提供
*/
MachbirdSDK.LogByAdjust(string eventToken)
# GDPR
# 1. GDPR 相关 API
判断是否欧盟用户
exit: ⌘↩
MachbirdSDK.IsEurope();设置个性化广告是否开启
exit: ⌘↩
MachbirdSDK.SetPersonalizedAdAgree(bool agree);判断当前用户是否同意个性化广告
exit: ⌘↩
MachbirdSDK.IsPersonalizedAdAgree();打点-授权界面展示时
exit: ⌘↩
MachbirdSDK.LogGdprPageShow();打点-授权界面用户点击同意时
exit: ⌘↩
MachbirdSDK.LogGdprAgree();
# 2. 产品里的 GDPR 处理流程
- 启动时判断是否欧盟用户
- 如果是欧盟用户并且没有同意过授权弹窗,则弹窗提示授权,用户必须点击弹窗里的"Start"按钮后,才能进入游戏。弹窗内容示例见下面。
- 如果是欧盟用户并且之前同意过授权弹窗(即使后来在设置里关闭了个性化广告),则直接进入游戏
- 如果不是欧盟用户,则不用弹窗,直接调用 API 设置个性化广告开启,进入游戏
- 在游戏设置界面,增加以下入口:
- 隐私协议查看按钮
- 用户协议查看按钮
- 个性化广告开关
- 删除数据按钮
上面提到的弹窗内容和设置界面需由 SDK 对接方进行 UI 设计
# 3. 授权弹窗

可互动元素:
- Start 按钮:点击即同意授权弹窗内的内容,游戏需要自己记录用户已经同意过授权弹窗(以后就再也不显示授权弹窗,除非清数据),同时调用
MachbirdSDK.SetPersonalizedAdAgree(true) - User Agreement: 点击后用网页打开用户协议: http://gc-static.machbird.com/machbird/machbird/GameUserAgreement.txt
- Privacy Policy: 点击后用网页打开隐私协议: http://gc-static.machbird.com/machbird/machbird/GamePrivacyPolicy.txt
- 关闭按钮:点击即不同意此界面的内容,退出应用
弹窗文字参考:
Welcome to Amazing Fish
Machbird takes your privacy and data security seriously. Before you get started though, our team wanted to let you know that upon getting your consent we will use some of your usage information to improve the game quality and will share certain of your data with our ads partners, so that you can be presented with ads that are relevant for you. You may check out our privacy policy to know more detail. If you're ever not interested in sharing your data, you can always re-adjust your settings.
START
By clicking on‘START’, you certify that you’re over fifteen, have read and accepted our User Agreement and Privacy Policy.
# 4. 设置界面
可互动元素:
- 查看隐私协议按钮:点击后用网页打开隐私协议地址
- 查看用户协议按钮:点击后用网页打开用户协议地址
- 个性化广告开关:通过
MachBirdSDK.IsPersonalizedAdAgree()来判断当前开关状态,通过MachBirdSDK.SetPersonalizedAdAgree(true/false)来设置新的状态
- 个性化广告开关:通过
- 清除本地数据按钮:点击后清空应用本地数据
# 5. 如何验证
我们是基于手机 SIM 卡归属国来判断是否欧盟的,如果想验证在欧盟用户手机上,产品是否会弹窗提示,但是手上又没有欧盟国家的 SIM 卡,可按以下步骤来模拟欧盟用户:
由于 Unity 默认设置“读取存储空间”权限只在 Android4.4 下声明,所以测试只能使用 Android4.4 以下的手机测试,或者导出 Android 工程后修改 AndroidManifest.xml 去掉该限制
打一个 Debug 包,安装,先不启动。Debug 包指的是在 Unity 里打包要勾选"Development Build"。

放置一个配置文件到手机 SD 卡根目录下,machbird_test.prop
去应用设置里开启“读取存储卡权限”
运行应用,看看是否弹窗出来
# 游戏中心
**目前游戏中心功能均不支持 iOS!**
# 1. 开屏互推
开屏场景方式
将 Assets\Machbird\GameCenter\Splash 场景添加到 Build Setting 中,并且设置为开始场景。

avatarEnter a caption for this image (optional)
# 2. 互推视频卡片
- 将
GameCenter/Resources文件夹下的VideoFrame预制体拖入想要放置的Canvas界面中,如主界面,结算页面等。 - 调整
VideoFrame的Scale与position以适应原有布局,直接调整控件的宽高可能会出现布局无法对齐的问题。 - 在包含
VideoFrame的界面展示的时候调用PlayerController.Instance.Play()播放视频。 - 当包含
VideoFram的界面关闭的时候调用PlayerController.Instance.StopPlay()停止播放。
# 3. 差评拦截
注意事项
- 使用的时候需要修改
ProductID,发布的时候修改接口地址为Release,修改方法在下面。 - 不需要将
prefab放到场景中
资源位置
差评拦截界面的prefab位于RateSystem/Resources文件夹下,图片资源位于RateSystem/Resource/Texture文件夹下
使用方式
在修改
prefab上RatePanelController脚本的ProductID,值由运营人员提供。
接口地址
编译 Debug 版本时使用的是测试环境地址,编译 Release 版本时使用的是正式环境地址。
在需要展示的时候调用下面方法
exit: ⌘↩
RatePanelController.ShowPanel(Action onLikeButtonClicked, Action onDislikeButtonClicked, Action<string> onSendButtonClicked, Action<RatePanelType> onPanelClose)参数说明
onLikeButtonClicked: 点击喜欢按钮onDislikeButtonClicked: 点击不喜欢按钮onSendButtonClicked: 点击发送按钮,参数是要发送的文本信息onPanelClose: 关闭Panel回调,参数是当前关闭时候处于那个界面中
素材替换
1.图片资源
素材位置位于ReteSystem/Resources/Texture文件夹下,开发人员可根据名字自行替换图片素材,保持名称不变。

2.字体文件
如果有替换字体的需求,请开发人员将字体文件拖入到prefab上RatePanelContoller脚本的Font字段中

# 文件云控
我们有时候想把游戏里的一些控制参数做成可以动态调整,比如第 N 关出广告/新手第一次奖励 N 金币等等,在游戏上线后,可以快速调整这些参数来观察数据变化,而不需要修改代码发版这么麻烦而耗时。所以,Machbird SDK 支持随时在后台下发一个配置文件到用户手机,配置文件里可以包含上面说的这种控制参数,然后游戏通过 Machbird SDK 提供的 API 实时获取到最新的配置,即可做到快速调整游戏线上版本的行为,提高测试验证效率。
# 云控文件有什么限制?
Machbird SDK 只是一个文件下发通道,对文件格式不做要求,但是考虑到用户流量和历史经验,有以下说明:
- 文件名:文件名没有限制
- 文件内容:内容格式不限,文件大小不超过 10K(一般内容格式推荐用 JSON)
# 如何获取云控文件内容
string fileContent = MachbirdSDK.GetCloudFileContent("test.json");
# 默认云控文件内容
- 当服务器没有下发云控文件时,上面的 API 返回一个空字符串,可以以此来判断是否有云控下发文件
- 可以在 Android 的 assets 目录下放一个同名的文件,内容是默认配置,这样 Machbird SDK 在获取该文件名队员的内容时,会优先使用云控下发的内容,如果没有则使用 assets 目录下的同名文件内容,均没有,才返回空字符串