在导入阿里 坑神SDK 时的新发现。

1.
随便建一个    . gradle  后缀名  文件。

比如说起名叫
config . gradle



内容如下::


ext {

/**
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 * 导入狗日的阿里云短视频SDK
 */

    projectVersion = '3.0.0-2017.1.22'

    externalAndroidBuildGradlePlugin = 'com.android.tools.build:gradle:2.2.0'

    externalAndroidAppCompatV7 = 'com.android.support:appcompat-v7:24.2.1'
    externalAndroidCardView = 'com.android.support:cardview-v7:21.0.+'
    externalAndroidMultiDex = 'com.android.support:multidex:1.0.1'
    externalAndroidRecyclerView = 'com.android.support:recyclerview-v7:24.2.1'
    externalAndroidSupportV13 = 'com.android.support:support-v13:23.4.0'
    externalAndroidSupportV4 = 'com.android.support:support-v4:23.4.0'
    externalAndroidDesign = 'com.android.support:design:24.2.1'


    externalAndroidTestEspressoCore = 'com.android.support.test.espresso:espresso-core:2.2.2'
    externalAndroidTestRunner = 'com.android.support.test:runner:0.4.1'

//    externalAndroidAsyncHttp = 'com.loopj.android:android-async-http:1.4.9'
//    externalAutoFactory = 'com.google.auto.factory:auto-factory:1.0-beta2'
//    externalDagger = 'com.google.dagger:dagger:2.0.1'
//    externalDaggerCompiler = 'com.google.dagger:dagger-compiler:2.0.1'
    externalDexmakerDx = 'com.crittercism.dexmaker:dexmaker-dx:1.4'
    externalDexmakerMockito = 'com.crittercism.dexmaker:dexmaker-mockito:1.4'
//    externalFastJson = 'com.alibaba:fastjson:1.2.5'

    externalHamcrestLibrary = 'org.hamcrest:hamcrest-library:1.3'
//    externalInject = 'javax.inject:javax.inject:1'

    externalJSR305 = 'com.google.code.findbugs:jsr305:3.0.0'
    externalMockito = 'org.mockito:mockito-core:1.10.19'
    externalOrmLiteAndroid = 'com.j256.ormlite:ormlite-android:4.48'
    externalGlide = 'com.github.bumptech.glide:glide:3.7.0'
    externalGlideOkHttp = 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
    externalOKHTTP = 'com.squareup.okhttp3:okhttp:3.2.0'
    externalGSON = 'com.google.code.gson:gson:2.8.0'
    externalOKIO = 'com.squareup.okio:okio:1.12.0'



    externalPagerSlidingTabStrip = 'com.astuetz:pagerslidingtabstrip:1.0.1'

    externalEasyPermissions = 'pub.devrel:easypermissions:0.2.1'

    externalJunit = 'junit:junit:4.12'

    externalCompileSdkVersion = 25
    externalBuildToolsVersion = "25.0.1"
    externalMinSdkVersion=15
    externalTargetSdkVersion=25
}


然后在  Module 的 build  里面的  根目录  ,   或者    Project项目 的  build  里面的  buildScript {  }  目录



apply from: 'config.gradle'




这岂不是
这岂不是
这岂不是

这岂不是  和  PHP 很像很像很像吗????



require() 函数


或者 


include() 函数


然后变量值都可以用了啊啊啊啊

ext  列表名,  或许就意味着
global  关键字    在PHP中

只有声明了,  才能全局使用







2.非常诡异,非常     邪性的一点

诡异   +   邪性



这样子能写,

哪怕是   compile     ==     25

而官方限定死的     24.2.1

以下代码也可以光明正大的跑通

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile(project(':AliyunSnap:snap_core')) {
        transitive = false
    }


    compile externalAndroidAppCompatV7
    compile externalAndroidDesign

    compile externalJSR305
    compile externalGlide
    compile externalEasyPermissions
    compile externalOKHTTP
    compile externalGlideOkHttp
    compile externalOKIO
    compile externalGSON

}




而以下这样写就不行


    compile 'com.android.support:appcompat-v7:24.2.1'//此处报错
    compile 'com.android.support:design:24.2.1'//此处报错

    compile 'com.google.code.findbugs:jsr305:3.0.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'pub.devrel:easypermissions:0.2.1'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
    compile 'com.squareup.okio:okio:1.12.0'
    compile 'com.google.code.gson:gson:2.8.0'

}



可见非常   邪性    ,    血腥      ,      邪性


但无疑非常好用。




3.

一些关键词

compile

Conflict with dependency

App   ( 3.0.0 )

test App  ( 2.0.1 )

Resolved versions

testCompile

androidTestCompile

configurations.all  { }  
resolutionStrategy  { }
force  ' 仓库:模块:版本  '
androidTestCompile (' 仓库:模块:版本  ') {
    exclude module: '模块名称'
}


以及,参照以下文章

https://github.com/square/assertj-android/issues/193

https://stackoverflow.com/questions/33317555/conflict-with-dependency-com-android-supportsupport-annotations-resolved-ver  【正解】

https://stackoverflow.com/questions/28999124/resolved-versions-for-app-22-0-0-and-test-app-21-0-3-differ

https://www.google.com.hk/search?safe=strict&source=hp&q=Error%3AConflict+with+dependency++Resolved+versions&oq=Error%3AConflict+with+dependency++Resolved+versions&gs_l=psy-ab.3...226.39418.0.40394.6.6.0.0.0.0.99.99.1.1.0....0...1.1.64.psy-ab..5.0.0.1RofdFC0v9c【搜索】



【已解决】


4.

(1)
Error:

Dependency  XXXXX:  unspecified on project app resolves to an APK archive which is not supported as a compilation dependency


可能是:创建了两个Module,其中一个Module依赖另一个Module而导致了出现该问题


解法:

  1. apply plugin: 'com.android.application'  

修改为
  1. apply plugin: 'com.android.library'  

(2)

Error:
Library projects cannot set applicationId. applicationId is set to 'package_name' in default config


Module  —— build . gradle ——  android {         defaultConfig     {            
                                                                           applicationId    "xxx包名“     //注释掉。
                                                            }             }



以上两种解法,
均来自于同一篇文章

http://blog.csdn.net/u012336923/article/details/48049479    【csdn博客:yao伟斌







4.发现一点——————惊天大谜团。


阿里云短视频的  Demo 是   SDK  25 的版本,
却可以使用
24.2.1 的V7包。


android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"


compile externalAndroidAppCompatV7
compile externalAndroidDesign



externalAndroidAppCompatV7 = 'com.android.support:appcompat-v7:24.2.1'
externalAndroidDesign = 'com.android.support:design:24.2.1'


至少编译器错误层面上的区别,

在于从 外界ext  compile导的不会报错。
直接写固定的版本号,必定报错。




后来再三查看,好像只解决了编译器在  dependencies中的  运行:

即————
                    使得  compileSDK  为  25,26  的Module  ,  能够使用    24.0.0  的  v7  support  (以及其它各  版本同步包)


但仍然解决不了,
其它所有第三方库中,    因为已封装,      无法直接调换已写死的    v7  support  (以及其它各  版本同步包)      的问题
即,只能解决【当前】        【所处项目】        的【问题】。

仍然无法穿透,

,,,,,,,,,,,,,,,,,,,,,,,,,,





5.改用【标准版】
基础版的内容,连客服也说了,除了逐个改第三方库的路径,别无别法。

标准版:

1.问题一
unable to delete directory
解决办法,将  报错的build路径,整个删掉。重新来。

2.问题二

明明已经导入了DownloaderManager包,偏偏说找不到。

更改build:gradle 插件版本,即可   2.20 ————> 2.3.3

'com.android.tools.build:gradle:2.3.3'



6.
    if(key == R.mipmap.demo_camera_icon){
           Intent camera = new Intent("com.duanqu.qupai.action.camera");
    }


然后Manifest文件,
<activity
    android:name="com.aliyun.demo.recorder.CameraDemo">
    <intent-filter>
        <action android:name="com.duanqu.qupai.action.camera"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>


可见,是从这里开始调取的。





7.大神文章,      解决所有傻逼阿里依赖。

【踩坑速记】二次依赖?android studio编译运行各种踩坑解决方案,杜绝弯路,总有你想要的~

http://www.cnblogs.com/liushilin/p/6068098.html


针对《基础版》,有可能达到必杀效果!!!

【等待尝试  ing  】


【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】
【等忙完了一定要去尝试!!!!!!!!!!!!!!!!!!!!】


8.
结构分析【标准版】

Demo:引导页面,进入各分支SDK的菜单页面。
AliyunCrop:crop_demo:视频拼接与裁剪页面。
AliyunRecorder:record_demo:视频录制页面。
AliyunVideoSdk:仅包含arr和gradle的模块。
AliyunHelp:展示版权文本的页面。
AliyunFileDownLoader:downloadermanager:提供下载各种彩图动画特效的下载模块。(如果不加入彩图动画,可以去掉。)
STMobileJNI:(据说是要,让用户自己选择)怎样显示彩图动画、怎样捕捉人脸位置加特效。(但因为没有交费,没有授权,所以Demo中不可用。)【而且,捕捉人脸和彩图动图,都是专业版才有的功能(那你他娘的放在这里干嘛?)】
AliyunView:用到的诸多自定义特效控件。

9.

有空要研究一下下面的写法:

configurations.maybeCreate("default")
artifacts.add("default", file('AliyunSdk-RC.aar'))


在一个Module中,只有
一个    build.gradle    和一个    AliyunSdk-RC.arr    文件

build.gradle    只有两行代码。


而其它模块对这个写法的模块的导入为

dependencies {
    compile(project(':AliyunVideoSdk')) {
        transitive = false
    }
}





10.【最新消息】

经过与阿里的安卓程序员的联系,

他们一时半会也找不到根本原因,只说和arr的分包有关。

他们给了我一个
v7   support  包  为  25.3.1 的版本。

经过我的导入,目前问题暂时得到了解决。


问题暂时得到了解决!!!

问题暂时得到了解决!!!

问题暂时得到了解决!!!

问题暂时得到了解决!!!


问题暂时得到了解决!!!


以下是调试的大体经过,


基本按照【基础版3.3.1】的流程来的,

不同之处我列在下面:

1.注释了  v7包 为  25.4.0  的第三方库Compile 。
保证都是小于等于  25.3.1 的情况。


2.根据


编译器的报错结果,分别逐条对比,添加force如下。  (根据每个人个人情况)





configurations.all {//【测试】【测试】【测试】【测试】【测试】【测试】
    resolutionStrategy {
        failOnVersionConflict()
        force 'org.jetbrains.kotlin:kotlin-stdlib:1.1.3-2'


        force 'com.android.support:appcompat-v7:25.3.1'
        force 'com.android.support:recyclerview-v7:25.3.1'
        force 'com.android.support:support-compat:25.3.1'
        force 'com.squareup.okio:okio:1.12.0'
        force 'com.squareup.okhttp3:okhttp:3.2.0'
        force 'com.squareup.retrofit2:retrofit:2.3.0'
        force 'com.google.code.gson:gson:2.8.0'
        force 'com.android.support:support-annotations:25.3.1'
        force 'com.android.support:support-v4:25.3.1'


        force 'com.squareup:javapoet:1.8.0'
        force 'com.google.code.findbugs:jsr305:3.0.0'
    }
}




然后操作的原理,和技术备忘录,
如下:


然后我的一些自己的尝试总结如下:


1.将短视频SDK的  v7  包  指定为唯一的最高版本标准。然后所有在此版本之下的第三方库,都是有着自己的向下兼容机制的,所以都可以得到合理解决。


2.然后解决兼容问题。用 configurations.all    里面的    resolutionStrategy   策略,
用    failOnVersionConflict    和    forece    这两个方法,
来根据编译器的实时报错,进行版本的强制修改。



3.以上的情况,都是建立在    短视频SDK    的  v7    包,高于所有第三方库的    v7包的情况之下。



4.若存在某一  第三方库的v7版本,
高于短视频SDK    的标准v7版本。(当前为    25.3.1    )
则以上的向下兼容机制,则失效。
而且,很有可能,产生预料之外的错误(版本冲突)。









11.并且,
我还预备给他们两条建议,————更好的使用第三方库:


建议一:

(1)
除了利用

resolutionStrategy
的
force之外,

还有一种
待选解法

具体解决方案为:由于很多第三方包都会用到v4支持包,这样在你导入多个支持的时候难免会出现这样的错误,只需在build.gradle里面添加上

configurations {

  all*.exclude group: 'com.android.support', module: 'support-v4'

}

参见大神文章:

【踩坑速记】二次依赖?android studio编译运行各种踩坑解决方案,杜绝弯路,总有你想要的~

里面的第二点,就是讲这个的。



(2)

所有的activity  xml  命名, 
一、不应让用户避让自己的  xml文件命名。

二、应该自己想办法,比如在  xml文件名、各种value属性,的后面,加上自己独一无二仅有的不可能冲突的后缀名。应该是自己主动避让客户。














整体上!学习到了非常多的东西!自学,是最厉害最无法阻拦的解法!

荣神益人!







进入常规项目阶段:
12.

base-64  加密的  UploadAddress 字段:



eyJFbmRwb2ludCI6Imh0dHBzOi8vb3NzLWNuLXNoYW5naGFpLmFsaXl1bmNzLmNvbSIsIkJ1Y2tldCI6ImluLTIwMTcwODAzMTg1MDE1OTE4LWlyMjVsajE2dGwiLCJGaWxlTmFtZSI6InZpZGVvLzEwQkREMzBFLTE1RTE4MEJFMTNELTExOTEtNzAwNS00MDUtMDE2MTgubXA0In0=

变为了:

eyJFbmRwb2ludCI6Imh0dHBzOi8vb3NzLWNuLXNoYW5naGFpLmFsaXl1bmNzLmNvbSIsIkJ1Y2tldCI6ImluLTIwMTcwODAzMTg1MDE1OTE4LWlyMjVsajE2dGwiLCJGaWxlTmFtZSI6InZpZGVvLzEwQkREMzBFLTE1RTE4MEJFMTNELTExOTEtNzAwNS00MDUtMDE2MTgubXA0In0\u003d


末位的等号,变了


解析出来的Json也由

{"Endpoint":"https://oss-cn-shanghai.aliyuncs.com","Bucket":"in-20170803185015918-ir25lj16tl","FileName":"video/10BDD30E-15E180BE13D-1191-7005-405-01618.mp4"}

变为了

{"Endpoint":"https://oss-cn-shanghai.aliyuncs.com","Bucket":"in-20170803185015918-ir25lj16tl","FileName":"video/10BDD30E-15E180BE13D-1191-7005-405-01618.mp4"}.Ӎ݀


相关解决文章为:

使用Gson将对象类转成Json对象时出现\u003d的问题

http://blog.csdn.net/taven/article/details/42706451


这种情况,如果Student属性中的某个值包含有=,会变为\u003d的情况


只需将Gson的初始化修改

[java]  view plain  copy
  1. Gson gson = new GsonBuilder().disableHtmlEscaping().create();  


对于

retrofit = Retrofit.Builder().baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create(gson))

没用。

那么,手动转化吧:


uploadAddress = uploadAddress?.replace("\\u003d","=")//【解决Gson的Bug。】


13.


全屏,SDK不提供现成方法。      手动调整。


竖向:

//自己的一些控件,进行显示
rl_titlebar_012.visibility = View.VISIBLE
rl_namebar_012.visibility = View.VISIBLE
ll_menubar_public.visibility = View.VISIBLE
ll_describebar_012.visibility  = View.VISIBLE
btn_join_005.visibility = View.VISIBLE



横向:


//自己的一些控件,进行隐藏
rl_titlebar_012.visibility = View.GONE
rl_namebar_012.visibility = View.GONE
ll_menubar_public.visibility = View.GONE
ll_describebar_012.visibility  = View.GONE
btn_join_005.visibility = View.GONE



然后


ViewGroup.LayoutParams.MATCH_PARENT.let { params.height = it; params.width = it }
不起作用

windowManager.defaultDisplay
        .let { params.width = it.width*3; params.height = it.height*3 }
不起作用

var trueParams = rl_wrap_match_home_player.layoutParams
windowManager.defaultDisplay
        .let { trueParams.width = 500;trueParams.height = 500 }

不起作用

甚至天才般的思考:

windowManager.defaultDisplay
        .let { params.width = it.height;params.height = it.width }

都不起作用。



A
match_home_player.changeScreenMode(AliyunScreenMode.Full)//全屏模式




B
ViewGroup.LayoutParams.MATCH_PARENT.let { params.height = it; params.width = it }

的前后顺序交换,都不起作用。




match_home_player.layoutParams = params
也不起作用。

params.width  = windowManager.defaultDisplay.width
params.height  = windowManager.defaultDisplay.height
match_home_player.layoutParams = params
手动一个个字,打进去,也不起作用。




14、
外层wrap嵌套可以改layoutParams,

内层的播放器不可以改layoutParams



始终扩不到全屏。






14问题已解决。。。。。【核心方案是:1.width必须写  wrap_content  或者  match_parent  。  2.  height必须写  dp  或  px   。   3.  其他的任意占用面积的UI,都gone掉。4.在onConfigurationChanged里面,  设置对应的尺寸变化方法。   5.  说不定有其他   6.说不定有其他】



15.

自己设计了一套,  用Surface  显示,   player  管理流程的,   基本的播放。


以及自己设计的高级版UI。


16.

自己设计了一套,  List中    播放器Item 的全套生命管理系统。


17.




基础版的短视频录制,这个  选择相册  的按钮,应该用什么方法去隐藏呢?





答曰:

snap_demo 里style文件里面<item name="qusnap_gallery_icon_visibility">visible</item>  该属性设置为gone就可以了






18.

多Item列表的播放器模式


和单列表item的播放器模式


的抽取与组合。



19.

全画面点击。

而且简单重排了一下生命周期中的方法。


20.

自动播放处理。


21.


播放器

音量设置

//TODO 测试
TLog.l("现在监测到的音量是——————${playerHashMap[index]?.player?.volume}")

每次变动7个。


音量从 0 -- 100 。  有14阶变量。


可以手动  setVolume ( Int  )


和  手动   getVolume (  Int  ) 



 

22.

设置屏幕亮度


  * 设置屏幕亮度
    * 0 最暗
    * 1 最亮
    */
    public void setBrightness(float brightness) {
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.screenBrightness = lp.screenBrightness + brightness / 255.0f;
        if (lp.screenBrightness > 1) {
            lp.screenBrightness = 1;
        } else if (lp.screenBrightness < 0.1) {
            lp.screenBrightness = (float) 0.1;
        }
        getWindow().setAttributes(lp);

        float sb = lp.screenBrightness;
        brightnessTextView.setText((int) Math.ceil(sb * 100) + "%");
    }

直接设置整机的屏幕亮度代码。


23.

设置了好久。


发现  马云视频播放器的   setVolume   这个api  ,是没用的


无论输入什么进去,  都是播放器的   音量为   0


playerHashMap[index]?.volumeBtn?.setOnClickListener {
    /**
     * 如果播放器音量大于0。则记录下播放器音量,并重新将音量设为0
     * 如果播放器音量已为0。则将播放器音量设置为上次存储的音量。
     */

    TLog.l("根据系统音量,此时当前系统媒体音量是 ${getSystemMediaVolume(true)}", "Volume")


    TLog.l("此时播放器的音量是  ${playerHashMap[index]?.player?.volume}", "Volume")
    TLog.l("现在存储的上次音量值为   ${playerHashMap[index]?.original_volume},然后开始判断", "Volume")
    playerHashMap[index]?.original_volume?.let {
        when (it > 0) {
        /**
         * 若大于0
         */
            true -> let {
                TLog.l("走大于0的分支  :设置之前前前,播放器的音量为${playerHashMap[index]?.player?.volume}", "Volume")


                val savedVolume = playerHashMap[index]?.player?.volume
                playerHashMap[index]?.original_volume = savedVolume

                playerHashMap[index]?.player?.volume = 0//设置为0

                TLog.l("设置之后后后,播放器的音量为${playerHashMap[index]?.player?.volume}", "Volume")
            }
        /**
         * 若小于等于0
         */
            false -> let {
                TLog.l("走小于等于0的分支  :设置之前前前播放器的音量为${playerHashMap[index]?.player?.volume}", "Volume")

                playerHashMap[index]?.player?.volume = playerHashMap[index]?.original_volume ?: 50//设为上一次的值。如为null则50

                TLog.l("设置之后后后播放器的音量为${playerHashMap[index]?.player?.volume}", "Volume")

            }
        }
    }
}



哪怕有乘了一百倍后,也照样无效。


后来发现。。。。

上面那个判断分支写错了:

TLog.l("现在存储的上次音量值为   ${playerHashMap[index]?.original_volume},然后开始判断", "Volume")



应该是:

playerHashMap[index]?.player?.volume?.let {



写着写着写多了,就糊涂了。



24.

系统的  Call  通话音量

从  0  最小  到   7  最大  , 有    7  级



系统 的   Media(Music一样的) 媒体音量

从  0  最小 到   15最大  , 有    15   级



马云视频播放器,    

是从   0   - -----  --  100   ,总共有  100   级。



25.


经过很多微细的调整和Log调整之后。

马云视频播放器的音量功能,调通了。

音量是可以调节的。
没问题,只是SDK比较绕。


还要注意有一点。


public class PlayerProxy implements IAliyunVodPlayer

里面是这样写的

public void setVolume(int volume) {
    if(this.mAvmPlayer != null) {
        this.mAvmPlayer.setVolume((float)volume * 1.0F / 100.0F);
    }
}

public int getVolume() {
    if(this.mAvmPlayer == null) {
        return 0;
    } else {
        float volume = this.mAvmPlayer.getVolume();
        return (int)(volume * 100.0F);
    }
}





26.


firstVisibleItem = layoutManager.findFirstCompletelyVisibleItemPosition()//完全可见。————?
firstVisibleItem = layoutManager.findFirstVisibleItemPosition()//只要有一点点部分可见。——————?


RecyclerView.LayoutManager

找到的方法——————

一、第一个为部分可见的条目


二、第一个全部可见的条目



最后一个以此类推




感觉。。。


这API很神奇


可以大作文章




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值