1) 切换到单独的分支,迁移完成前最好不进行功能开发,然后将代码备份一份,防止迁移失败
2) 检查项目中每个module中support库的依赖,将版本升级到28.0.0,需要将compileSdkVersion升级到28,保证项目正常能编译通过
3) 在Android Studio中Refactor->Migrate to AndroidX完成迁移
4) 编译项目,如果有编译错误,解决即可(如第三方依赖库版本不支持androidx需要升级到新版本,例如ButterKnife) repositories {
        ...
        maven { url 'https://nexus.plaso.cn/repository/maven-public/'}
    }android {
    ……
    defaultConfig {
        ……
        minSdkVersion 24  // 配置>= 24
        targetSdkVersion 33 // 配置 >= 33
        ……
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
}
dependencies {
    ...
    implementation( 'cn.plaso:styleupime:$version')
}
verride fun onCreate() {
    super.onCreate()
    ...
    resProvider = object : IResourceProvider {
        override fun supportResourceCenter(): Boolean {
            //是否支持定制化资料中心,返回true代表支持,false代表不支持
            return false
        }
        override fun showResourceCenter() {
             //显示 APP 定制化资料中心,在此处实现跳转到定制化资料中心页面
        }
        override fun dismissResourceCenter() {
             //关闭 APP 定制化资料中心
        }
        override fun getExtFileName(extFileId: Any?, resouceCallback:IResourceCallback?) {
            //APP 根据传入的文件标识内容返回其可以访问的完整 URL
        }
        override fun signQuery(queryMap: MutableMap<String, Any>?, cb: SignCallback?): Boolean {
            //请求SDK Client进行参数签名,窗口模式下,插入文件,需要从服务器获取签名
            if (queryMap != null) {
                queryMap["appId"] = Config.appId //Config.appId填写从伯索获取的appId,这个参数是必需的
                queryMap["validTime"] = 120
                queryMap["validBegin"] =  System.currentTimeMillis() / 1000
                //根据queryMap,appKey生成一个query
                val signedQuery = SignHelper.sign(queryMap, Config.appKey) //Config.appKey填写从伯索获取的appKey
                cb?.onSignCompleted(signedQuery)
            } else {
                cb?.onSignCompleted(null)
            }
            return true
        }
        override fun getWebviewUrl(type: Int, callback: IUrlCallback?) {
            //请求SDK Client是否有教材包的链接需要在课堂内打开
            callback?.onGetUrl("https://www.plaso.cn")
        }
    }
    //创建一个StyleUpime对象
    upime = StyleUpime.create(this, "demo", resProvider)
}
object SignHelper {
    /**
     * Sign the [params] with specific [signKey]
     */
    fun sign(params: MutableMap<String, Any>, signKey: String): String {
        val keys = params.keys.sorted()//将Map中的key按顺序排列
        val sortedParams = StringBuilder()
        for ((index, key) in keys.withIndex()) {
            if (index != 0) {
                sortedParams.append("&")
            }
            sortedParams.append("$key=${params[key]}")
        }
        val signature = encrypt(sortedParams.(), signKey)
        params["signature"] = signature;
        return buildQuery(params);
    }
    private fun buildQuery(params: MutableMap<String, Any>): String {
        val result = StringBuilder()
        for ((index, key) in params.keys.withIndex()) {
            if (index != 0) {
                result.append("&")
            }
            result.append("$key=${URLEncoder.encode(params[key].toString(), "UTF-8")}")
        }
        return result.()
    }
    private fun encrypt(encryptText: String, signKey: String): String {
        val algorithm = "HmacSHA1"
        val charset = Charset.forName("UTF-8")
        val data = signKey.toByteArray(charset)
        val secretKey = SecretKeySpec(data, algorithm)
        val mac = Mac.getInstance(algorithm)
        mac.init(secretKey)
        val rst = mac.doFinal(encryptText.toByteArray(charset))
        return BigInteger(1, rst).(16).toUpperCase()
    }
private fun startMiniLesson(lessonInfoWrap: LessonInfoWrap?) {
        val config = MiniLessonConfig()
        // config.openFileMode = openFileMode
        //微课支持新建和草稿两种形式,对于草稿可继续编辑
        if (lessonInfoWrap == null) { //新建
            if (!TextUtils.isEmpty(mini_title.text.())) {
                config.topic = mini_title.text.()      //"微课测试_" + Random(System.currentTimeMillis()).nextInt()
            }
            //设置草稿保存路径
            config.draftPath =
                "${getExternalFilesDir(null)?.absolutePath}/mini/${System.currentTimeMillis()}"
        } else { //草稿
            config.topic = lessonInfoWrap.lessonInfo.topic
            //设置草稿路径
            config.draftPath = lessonInfoWrap.lessonInfo.path
        }
        File(config.draftPath).also {
            if (!it.exists()) {
                it.mkdirs()
            }
        }
        config.supportDraft = supportSaveDraft;
        config.supportUndo = supportUndo;
        config.teachToolTypes = teachToolTypes
        config.openFileMode = openFileMode
        config.recordType = recordType
        config.enableInteractPpt = enablePptInteract
        var extraJson = JSONObject()
        extraJson.put("id", "weikebao_id1");
        config.extra = extraJson.();
        //启动微课,upime是step.4创建的StyleUpime对象
        upime.launchMiniLesson(config, object : IMiniLessonListener {
            override fun onMiniLessonReady(upimeBoard: UpimeBoard?) {
                // 微课准备完成,获得UpimeBoard对象,可用于资料中心的资料插入等操作
            }
            override fun onClosed() {
                //微课退出通知
            }
            override fun onDraftSaved(draft: LessonInfo?) {
                 //保存草稿通知
            }
            override fun onFinished(info: LessonInfo?) {
                //微课录制完成通知
            }
            override fun onSkinChanged(skinId: Int) {
                //微课背景皮肤改变通知
            }
        })
    }
| ** topic ** | ** String ** | 否 | - | **微课主题名称 ** | 
|---|---|---|---|---|
| draftPath | String | 是 | - | 微课草稿本地保存路径 | 
| openFileMode | int | 否 | null | 文件打开模式 | 
| supportDraft | Boolean | 否 | true | 是否支持存为草稿 | 
| 参数名 | 参数类型 | 是否必要 | 默认值 | 参数说明 | 
| enableInteractPpt | Boolean | 否 | false | 是否开启PPT交互 | 
| teachToolTypes | int | 否 | 0 | 是否打开教具 | 
| supportUndo | Boolean | 否 | false | 是否支持撤销操作 | 
| recordType | int | 否 | 0 | 微课录制类型音频传:1视频传:2 | 
private fun preview(it: LessonInfoWrap) {
        //预览微课,upime是step.4创建的StyleUpime对象
        upime.playMiniLesson(it.lessonInfo.path, object : ILessonProvider {
            override fun getFileName(name: String?): String {
                //获取文件名
                return "$name"
            }
        })
    }fun deleteLesson(it: LessonInfoWrap) {
        if (it.status == RECORDED || it.status == EDITING) {
          //删除微课,upime是step.4创建的StyleUpime对象
           upime.deleteDraft(configKey, it.lessonInfo.path)
        } else {
           //删除本地微课或者上传到OSS的微课
        }
}implementation 'cn.plaso:styleupime:1.28.804'