API调用流程:①申请开通API调用权限
②获取API调用鉴权参数
③完成数据调用
②获取API调用鉴权参数
③完成数据调用
请求参数
返回数据
示例代码
请求示例
{{req_example}}
返回示例
{{res_result}}
错误码
配置环境
1.在module的gradle中配置
ndk {
abiFilters "armeabi","armeabi-v7a"
}
2.添加依赖(版本号可以替换为高版本或者低版本,但是不能保证兼容性,替换第三方库版本号后,请务必认真测试)
compile(name: 'diandu-vx.x.x', ext: 'aar')
compile(name: 'rjfoxit-vx.x.x', ext: 'aar')
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.liulishuo.okdownload:okdownload:1.0.4'
implementation 'com.liulishuo.okdownload:sqlite:1.0.4'
implementation 'com.liulishuo.okdownload:okhttp:1.0.4'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'org.greenrobot:eventbus:3.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.google.code.gson:gson:2.6.2'
implementation('jameson.io.library:library:0.0.1') {
exclude group: "com.android.support", module: "support-v4"
}
implementation 'com.shuyu:gsyVideoPlayer-java:6.0.2'
implementation 'com.rjsz.frame:xunfei:1.0.2'
implementation 'com.github.bumptech.glide:glide:4.8.0'
代码混淆
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe methods;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keepnames class com.liulishuo.okdownload.core.connection.DownloadOkHttp3Connection
-keep class com.liulishuo.okdownload.core.breakpoint.BreakpointStoreOnSQLite {
public com.liulishuo.okdownload.core.breakpoint.DownloadStore createRemitSelf();
public com.liulishuo.okdownload.core.breakpoint.BreakpointStoreOnSQLite(android.content.Context);
}
-dontwarn com.liulishuo.**
-keep class com.liulishuo.okdownload.** {*;}
-keep class com.rjsz.frame.download.**{*;}
-keep class com.rjsz.frame.diandu.PRDownloaderManager{
public *;
}
-keep class com.rjsz.frame.diandu.PRSDKManager{
public *;
}
-keep class com.rjsz.frame.diandu.PRViewManager{
public *;
}
-keep class com.rjsz.frame.diandu.config.PRStateCode{ *; }
-keep class com.rjsz.frame.diandu.callback.ReqCallBack{ *; }
-keep class com.rjsz.booksdk.bean.* { *; }
-keep class com.rjsz.frame.diandu.event.* { *; }
-keep class com.rjsz.frame.diandu.bean.* { *; }
-keep class com.rjsz.frame.diandu.webview.bean.* { *; }
-keep class com.rjsz.frame.diandu.utils.PRFileUtil { *; }
-keep class com.rjsz.frame.pepbook.bean.*{ *; }
-keep class com.rjsz.frame.pepbook.config.*{ *; }
-keep class com.rjsz.frame.pepbook.download.*{ *; }
-keep class com.rjsz.frame.pepbook.event.*{ *; }
-dontwarn com.edmodo.cropper.**
-keep class com.edmodo.cropper.** {*;}
-keep class com.foxit.sdk.** { *; }
-keep class com.foxit.uiextensions.** { *; }
-dontwarn com.foxit.sdk.**
-dontwarn com.foxit.uiextensions.**
-dontwarn com.iflytek.**
-keep class com.iflytek.**{*;}
初始化
在程序的入口处(Application),调用如下方法:
1.PRSDKManager.getInstance().init(this, appKey);
/**
* @param context
* @param appKey appKey分配的平台key 必填
*/
public void init(this, appKey)
2. 在程序的入口处,调用如下方法:
/**
* @param context Application
* @param appKey appKey分配的平台key 必填
* @param isShowCuntomBuyTip 是否自定义购买提示isShowCuntomBuyTip若为true 参见方法说明14,自定义用户提示交互
*/
PRConfig config = new PRConfig.Builder()
. setAppKey(appKey)// appKey分配的平台key 必填
. setIsShowCustomBuyTip (isShowCuntomBuyTip) //是否自定义购买提示
.build();
PRSDKManager.getInstance().init(context,config);
方法说明
1.同步订单接口
/**
* 第三方用户鉴权、绑定设备.
* 对接平台可在APP启动或用户订单状态发生变化时调用该方法
* @param userId 用户ID
* @param reqCallBack 网络请求回调
* success网络请求成功后回调(包括当前用户购买的书本和绑定的设备列表)
* fail网络请求失败后回调
*/
PRSDKManager.getInstance().syncOrder(userId, ReqCallBack );
2.获取用户绑定设备列表
在同步订单接口成功的回调里回传的json里含有此用户的所有绑定设备列表。
或同步订单后通过此方法获得PRSDKManager.getInstance().getDevices()
3.解绑用户设备
/**
* @param userId (用户id)
* @param list(集合,里面放有设备id)
如List String list = new ArrayList<>();
list.add(dev_id_1); 解绑设备id为dev_id_1的设备
list.add(dev_id_2); 解绑设备id为dev_id_2的设备
* @param ReqCallBack (回调接口)
*/
PRSDKManager.getInstance().removeDevices(userId, list, ReqCallBack)
4.根据bookid获取书籍信息
/**
* 根据book_id返回教材信息
*/
PRSDKManager.getInstance().getBookItemById(userId, book_id, ReqCallBack)
5.书本关闭获取页码,所属单元,标题
@Subscribe(threadMode = ThreadMode.MAIN)
public void getBookUnitAndTitle(CloseInfo info){}
6.书本关闭获取用户点击次数和时长
/**
* 关闭课本时回调
* @param infos
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void getTrackInfo(PlayTrackInfo clickReadInfo){}
7.获取书籍列表
/**
*
* @param userId 用户id
*/
PRSDKManager.getInstance().getAllBookList(userId, ReqCallBack)
8.打开课本
/**
*
* @param context (上下文)
* @param textbooksBean (BookList.TextbooksBean对象)
* @param boolean(是否为体验模式)
* @param num;打开页码 只有已购买状态才成能成功打开该页码
*/
PRViewManager.openBook(context, textbooksBean, boolean, int num);
或者
PRViewManager.openBook(context, textbooksBean, boolean);
9.下载课本
/**
*
* @param textbooksBean BookList.TextbooksBean对象)
*/
PRDownloaderManager.getInstance().download(textbooksBean);
a)暂停下载
PRDownloaderManager.getInstance().pauseDownloadOfBookID(book_id);
b)继续下载
PRDownloaderManager.getInstance().continueDownloadOfBookID(book_id);
c)下载状态监听
@Subscribe(threadMode = ThreadMode.MAIN)
public void downloadEvent(PRDownloadInfo downloadInfo)
PRDownloadInfo包含的状态码:
PRStateCode.STATE_ADD 6 开始下载
PRStateCode.STATE_ERROR 5 下载失败
PRStateCode.INTERFACE_ERROR 7 下载接口访问失败
PRStateCode.STATE_WAIT 1 暂停中
PRStateCode.STATE_DOWNLOAD 2 下载中
PRStateCode.STATE_SUCCESS 4 下载成功
10.删除课本
/**
*
* @param book_id (教材id)
* @return true:删除成功 false:删除失败
*/
boolean isDelete= PRDownloaderManager.getInstance().deleteBook(book_id);
11.获取缓存大小
/**
*
* @param context (上下文)
* @return cacheSize (缓存大小 单位为字节)
*/
long cacheSize = PRSDKManager.getInstance().getCacheDirSize(context);
12.清除缓存
/**
*
* @param context (上下文)
* @return isClean是否清除成功
*/
boolean isClean = PRSDKManager.getInstance().deleteCacheDir(context);
13.用户点击前往购买的回调
/**
* @param event 购买回调
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void handleSdkEvent(SdkEvent event) {
if (event.eventType == SdkEvent.EVENT_EXPERIENCE_END) {
//跳转购买页面
}
}
14.自定义交互提示用户购买或激活
/**
* @param event 提示购买回调
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void handleSdkEvent(SdkEvent event) {
if (event.eventType == EVENT_SHOW_BUY_TIP) {
Context mContext=event.activity;
//根据mContext自定义展示方式
}
}
15.判断书本是否已经下载
isDownloaded= PRDownloaderManager.getInstance().isDownloaded(book_id);
16.判断书本是否有更新
/**
*
* @param textbooksBean (BookList.TextbooksBean对象)
* @return true:有更新 false:没有更新
*/
hasUpdate= PRDownloaderManager.getInstance().hasUpdate(textbooksBean)
17.获取书本状态(是否已经订购)
hasBuy=PRSDKManager.getInstance().hasBuy(bookid)
18.获取目录
PRSDKManager.getInstance().getBookCatalogById(book_id,ReqCallBack)
19.自定义图片加载
设置图片加载器
/**
*
* @ param proxy 自定义图片加载器 继承BaseImageLoadProxy
*/
com.rjsz.frame.diandu.utils.ImageLoaderUtil.getInstance().setLoadImgProxy(BaseImageLoadProxy proxy)
20.自定义测评引擎
a)初始化时设置自定义测评引擎 new PRConfig.Builder().useCustomEvaluate(true)
b)打开教材前设置语音测评引擎
/**
* @ param thread自定义语音测评引擎 继承BaseEvaluateThread
* 测评结果通过EvaluateListener listener 回调
*/
com.rjsz.frame.diandu.thread.EvaluateManager.getInstance().setEvaluateThread(thread)
c)BaseEvaluateThread:
/**
* 开始测评
* @param textStr 句子原文
* @param evaStr 讯飞中测评语句
* @param audioPath 测评中生成录音文件(需要MP3格式&根据路径存放在对应位置)
*/
void startVoiceTest(String textStr, String evaStr, String audioPath);
/**
* 结束测评 解析测评结果 需要回调listener.onResult()方法返回结果
* 或回调 listener.onError()
*/
void parseResult();
/**
* @param listener 测评回调 通过该listener回调测评过程中的各种事件
*/
void setListener(EvaluateListener listener);
d)EvaluateListener:测评回调类
/**
* @param bean 返回测评结果
*/
void onResult(PREvaluateResult bean);
/**
* 测评报错
* @param errCode 错误码
* @param errStr 错误信息
*/
void onError(int errCode,String errStr);
/**
* 录入音频大小
* @param i 范围[0-30]
*/
void onVolume(int i);
e)PREvaluateResult:用于在句子中标记低分单词
Score:句子总得分List EvaluateScoreResult scoreResults;句子中每个词对应测评结果
f)EvaluateScoreResult
score:当前单词得分 五分制(满分五分)
word:当前单词内容
startIndex:当前单词在整句原文中的开始位置
配置环境
1.在 module 的 gradle 中配置
ndk {
abiFilters "armeabi-v7a"
}
2.添加依赖(版本号可以替换为高版本或者低版本,替换库版本号后,请务必认真测试)
compile(name: 'diandu-v2.1.0', ext: 'aar')
compile(name: 'rjfoxit-v7.3.0', ext: 'aar')
compile(name: 'xunfei-v1.0.2', ext: 'aar')
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'androidx.multidex:multidex:2.0.0'
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'org.greenrobot:eventbus:3.2.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.liulishuo.okdownload:okdownload:1.0.7'
implementation 'com.liulishuo.okdownload:sqlite:1.0.7'
implementation 'com.liulishuo.okdownload:okhttp:1.0.7'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
//2.1.0视频切片播放支持
implementation 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-java:v8.1.3-jitpack'
implementation 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:v8.1.3-jitpack'
implementation 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-armv7a:v8.1.3-jitpack'
//2.1.0数学教材多级目录支持
implementation 'com.yanzhenjie.recyclerview:support:1.3.2'
//2.1.0数学教材数学公式支持
implementation 'com.gitee.geduo_83:android_rich_textview:1.0.3'
implementation 'com.github.softwee:codeview-android:1.2.0'
//2.1.0 网络请求RxJava相关支持
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'
代码混淆
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe methods;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keepnames class com.liulishuo.okdownload.core.connection.DownloadOkHttp3Connection
-keep class com.liulishuo.okdownload.core.breakpoint.BreakpointStoreOnSQLite {
public com.liulishuo.okdownload.core.breakpoint.DownloadStore createRemitSelf(); public
com.liulishuo.okdownload.core.breakpoint.BreakpointStoreOnSQLite(android.content.Context);
}
-dontwarn com.liulishuo.**
-keep class com.liulishuo.okdownload.** {*;}
-keep class com.rjsz.frame.download.**{*;}
-keep class com.rjsz.frame.diandu.PRDownloaderManager{
public *;
}
-keep class com.rjsz.frame.diandu.PRSDKManager{
public *;
}
-keep class com.rjsz.frame.diandu.PRViewManager{
public *;
}
-keep class com.rjsz.frame.diandu.config.PRStateCode{ *; }
-keep class com.rjsz.frame.diandu.callback.ReqCallBack{ *; }
-keep class com.rjsz.booksdk.bean.* { *; }
-keep class com.rjsz.frame.diandu.event.* { *; }
-keep class com.rjsz.frame.diandu.bean.* { *; }
-keep class com.rjsz.frame.diandu.webview.bean.* { *; }
-keep class com.rjsz.frame.diandu.utils.PRFileUtil { *; }
-keep class com.rjsz.frame.pepbook.bean.*{ *; }
-keep class com.rjsz.frame.pepbook.config.*{ *; }
-keep class com.rjsz.frame.pepbook.download.*{ *; }
-keep class com.rjsz.frame.pepbook.event.*{ *; }
-dontwarn com.edmodo.cropper.**
-keep class com.edmodo.cropper.** {*;}
-keep class com.foxit.sdk.** { *; }
-keep class com.foxit.uiextensions.** { *; }
-dontwarn com.foxit.sdk.**
-dontwarn com.foxit.uiextensions.**
-dontwarn com.iflytek.**
-keep class com.iflytek.**{*;}
初始化
在程序的入口处(Application),调用如下方法:
1. 在程序的入口处,调用如下方法:
/**
*@param context Application
*@param appKey appKey 分配的平台 key 必填
*@param isShowCuntomBuyTip 是否自定义购买提示 isShowCuntomBuyTip 若为 true 参见方法说明
*14,自定义用户提示交互
*
*/
PRConfig config = new PRConfig.Builder()
. setAppKey(appKey)// appKey 分配的平台 key 必填
. setIsShowCustomBuyTip (isShowCuntomBuyTip) //是否自定义购买提示
.useCustomEvaluate(true)//是否使用自定义语音测评引擎默认使用讯飞
.build(); PRSDKManager.getInstance().init(context,config);
方法说明
1.同步订单接口
/**
*第三方用户鉴权、绑定设备.
*对接平台可在 APP 启动或用户订单状态发生变化时调用该方法
*@param userId 用户 ID
*@param reqCallBack 网络请求回调
*success 网络请求成功后回调(包括当前用户购买的书本和绑定的
*设备列表)
*fail 网络请求失败后回调
*/
PRSDKManager.getInstance().syncOrder(userId, ReqCallBack );
2.获取用户绑定设备列表
在同步订单接口成功的回调里回传的 json 里含有此用户的所有绑定设备列表。
3.解绑用户设备
/**
*@param userId (用户 id)
*@param list(集合,里面放有设备 id)
*如 List String list = new ArrayList<>();
*list.add(dev_id_1); 解绑设备 id 为 dev_id_1 的设备
*list.add(dev_id_2); 解绑设备 id 为 dev_id_2 的设备
*@param ReqCallBack (回调接口返回状态)
*/
PRSDKManager.getInstance().removeDevices(userId, list, ReqCallBack)
4.根据 bookid 获取书籍信息
/**
*根据 book_id 返回教材信息
*
*/
PRSDKManager.getInstance().getBookItemById(userId, book_id, ReqCallBack)
5.书本关闭获取页码,所属单元,标题
@Subscribe(threadMode = ThreadMode.MAIN) public void getBookUnitAndTitle(CloseInfo info){}
6.书本关闭获取用户点击次数和时长
/**
*关闭课本时回调
*@param infos
*/
@Subscribe(threadMode = ThreadMode.MAIN) public void getTrackInfo(PlayTrackInfo clickReadInfo){}
7.获取书籍列表
/**
*@param userId 用户 id
*/
PRSDKManager.getInstance().getAllBookList(userId, ReqCallBack)
8.打开课本
/**
*@param context (上下文)
*@param textbooksBean (BookList.TextbooksBean 对象)
*@param boolean(是否为体验模式)
*@param num;打开页码 只有已购买状态才成能成功打开该页码
*/
PRViewManager.openBook(context, textbooksBean, boolean, int num);
或者
PRViewManager.openBook(context, textbooksBean, boolean);
9.下载课本
/**
*@param textbooksBean BookList.TextbooksBean 对象)
*/
PRDownloaderManager.getInstance().download(textbooksBean);
a)暂停下载
PRDownloaderManager.getInstance().pauseDownloadOfBookID(book_id);
b)继续下载
PRDownloaderManager.getInstance().continueDownloadOfBookID(book_id);
c)下载状态监听
@Subscribe(threadMode = ThreadMode.MAIN)
public void downloadEvent(PRDownloadInfo downloadInfo)
PRDownloadInfo 包含的状态码:
PRStateCode.STATE_ADD
6 开始下载
PRStateCode.STATE_ERROR
5 下载失败
PRStateCode.INTERFACE_ERROR 7 下载接口访问失败
PRStateCode.STATE_WAIT
1 暂停中
PRStateCode.STATE_DOWNLOAD
2 下载中
PRStateCode.STATE_SUCCESS
4 下载成功
10.删除课本
/**
*@param book_id (教材 id)
*@return true:删除成功 false:删除失败
*/
boolean isDelete= PRDownloaderManager.getInstance().deleteBook(book_id);
11.获取缓存大小
/**
*@param context (上下文)
*@return cacheSize (缓存大小 单位为字节)
*/
long cacheSize = PRSDKManager.getInstance().getCacheDirSize(context);
12.清除缓存
/**
*@param context (上下文)
*@return isClean 是否清除成功
*/
boolean isClean = PRSDKManager.getInstance().deleteCacheDir(context);
13.用户点击前往购买的回调
/**
*@param event 购买回调
*/
@Subscribe(threadMode = ThreadMode.MAIN) public void handleSdkEvent(SdkEvent event) {
if (event.eventType == SdkEvent.EVENT_EXPERIENCE_END) {
//跳转购买页面
}
}
14.自定义交互提示用户购买或激活
初始化时设置自定义购买弹框 new PRConfig.Builder(). setIsShowCustomBuyTip (true)
/**
*@param event 提示购买回调
*/
@Subscribe(threadMode = ThreadMode.MAIN) public void handleSdkEvent(SdkEvent event) {
if (event.eventType == EVENT_SHOW_BUY_TIP) { Context mContext=event.activity;
//根据 mContext 自定义展示方式
}
}
15.判断书本是否已经下载
isDownloaded= PRDownloaderManager.getInstance().isDownloaded(book_id);
16.判断书本是否有更新
/**
*@param textbooksBean (BookList.TextbooksBean 对象)
*@return true:有更新 false:没有更新
*/
hasUpdate= PRDownloaderManager.getInstance().hasUpdate(textbooksBean)
17.获取书本状态(是否已经订购)
hasBuy=PRSDKManager.getInstance().hasBuy(bookid)
18.获取目录
PRSDKManager.getInstance().getBookCatalogById(book_id,ReqCallBack)
19.自定义图片加载
设置图片加载器
/**
* @ param proxy 自定义图片加载器 继承 BaseImageLoadProxy
*/
com.rjsz.frame.diandu.utils.ImageLoaderUtil.getInstance().setLoadImgProxy(proxy)
20.自定义测评引擎
a)初始化时设置自定义测评引擎 new PRConfig.Builder().useCustomEvaluate(true)
b)打开教材前设置语音测评引擎
/**
*@ param thread 自定义语音测评引擎 继承 BaseEvaluateThread
*测评结果通过 EvaluateListener listener 回调
*/
com.rjsz.frame.diandu.thread.EvaluateManager.getInstance().setEvaluateThread(thread)
c)BaseEvaluateThread:
/**
*开始测评
*@param textStr 句子原文
*@param evaStr 讯飞中测评语句
*@param audioPath 测评中生成录音文件(需要 MP3 格式&根据路径存放在对应位置)
*/
void startVoiceTest(String textStr, String evaStr, String audioPath);
/**
*结束测评 解析测评结果 需要回调 listener.onResult()方法返回结果
*或回调 listener.onError()
*/
void parseResult();
/**
*@param listener 测评回调 通过该 listener 回调测评过程中的各种事件
*/
void setListener(EvaluateListener listener);
d)EvaluateListener:测评回调类
/**
*@param bean 返回测评结果
*/
void onResult(PREvaluateResult bean);
/**
*测评报错
*@param errCode 错误码
*@param errStr 错误信息
*/
void onError(int errCode,String errStr);
/**
*录入音频大小
*@param i 范围[0-30]
*/
void onVolume(int i);
e)PREvaluateResult:用于在句子中标记低分单词
Score:句子总得分 List EvaluateScoreResult scoreResults;句子中每个词对应测评结果
f)EvaluateScoreResult
score:当前单词得分 五分制(满分五分) word:当前单词内容
startIndex:当前单词在整句原文中的开始位置
系统要求
由于依赖的福昕RDK已经升级到iOS10.0+,故人教点读SDK兼容的最低版本为iOS 10.0
使用说明
1.Cocoapods
在podfile中添加如下代码,然后pod install:
pod 'PEPNetworking', :git => 'https://github.com/PEPDigitalPublishing/PEPNetworking.git'
pod 'PEPBigData', :git => 'https://github.com/PEPDigitalPublishing/PEPBigData.git'
pod 'PEPReaderSDK', :git => 'https://github.com/PEPDigitalPublishing/PEPReaderSDK.git'
# 讯飞语音SDK
pod 'PEPiFlyMSC', :git => 'https://github.com/PEPDigitalPublishing/PEPiFlyMSC.git'
pod 'SSZipArchive'
pod 'iosMath'
指定版本号
podfile中可以通过如下方式指定版本号:
pod 'PEPReaderSDK', { :git => 'https://github.com/PEPDigitalPublishing/PEPReaderSDK.git', :tag => '2.0.0' }
2.手动接入
1.从Releases中下载指定版本,然后将其中的PEPReaderSDK.framework和PDFReaderSDKDiandu.xcassets导入项目中。
2.查看PEPReaderSDK.podspec中声明的依赖库,并保证这些依赖库也同样导入到项目中
FAQ
1. Include of non-modular header inside framework module xxxxxx
在项目的Build Setting中搜索“allow non-modular”,将出现的栏目中的“No”改为“Yes”
2. 福昕RDK的导入位置
FoxitRDK.framework是动态库,应导入到Embedded Binaries中,而不是Linked Frameworks And Libraries中
3. App打包上传App Store时报错(ERROR ITMS-90080、90087、90209、90125)
由于FoxitRDK.framework合并了真机和模拟器编译出的二进制文件,即在真机和模拟器上都能运行,且是动态库,以嵌入的方式(Embedded Binaries)导入项目的,故而Xcode在打包时无法自动去除x86_64和i386的二进制文件,需要增加脚本。
解决方案: TARGETS -> Build Phases -> 点击左上角加号选择New Run Script Phase-> 然后复制粘贴下面代码:
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done