简介:面向 Android 开发者的友盟分享 Social SDK 6.4.6 定制包,聚焦移动应用社交分享能力的快速接入,适合需要同时对接微信、QQ、微博以及 Facebook、Twitter 等平台的开发项目。压缩包以 zip 形式提供,体积约 58.92MB,文件清单与类型明细暂未披露,使用前可先核对包内目录、版本说明与依赖配置。资源包含 SDK 与配套 Demo,Demo 展示了初始化、分享接口调用、分享结果回调、自定义分享内容、自定义分享界面以及授权流程等典型用法,便于理解各模块的职责与调用关系;6.4.6 版本在兼容性、分享速度和接口稳定性方面有所优化,可结合更新日志评估升级价值。目前已有 217 人学习,适合希望减少多平台分别对接成本、需要参考示例完成分享功能集成的 Android 开发者,也可作为排查分享失败、回调异常与界面定制问题的对照材料。
1. 友盟分享 6.4.6 custom 安装前:先别急着把 aar 拖进 libs
上个月收尾一个模拟项目X,安装包里放的是友盟分享 umeng_android_social_sdk_6.4.6_custom,Gradle 同步一路绿,真机点分享却只转圈。这类 6.4.6 定制包最常见的翻车点不是代码写错,而是把标准版清单、渠道白名单和资源文件直接套过来。它适合正在维护老 Android 工程、又必须用定制渠道清单的开发者;装不好时表现为面板不弹、选完渠道闪退、release 包才报错。先按下面顺序核对环境,再谈导入。
2. 环境与包结构核对:友盟分享 6.4.6 custom 的版本取舍
2.1 先定 Android 侧组合,不要先动 SDK
拿到umeng_android_social_sdk_6.4.6_custom之后,我一般不会先改build.gradle里的依赖,而是先把工程现有组合记下来:AGP 版本、Gradle 版本、JDK 版本、compileSdk、targetSdk、minSdk、是否已经 AndroidX、有没有多模块。原因很直接,6.4.6 属于老版本 SDK,定制包又可能裁过渠道实现,工程侧一旦同时动 AGP 和 SDK,出问题后很难判断是哪一边引起的。常见做法是先用一个能编译通过的分支做基线,再单独加分享依赖,每次只改一个变量。
下面这段配置不是让你照抄版本号,而是把需要对齐的字段摆出来。compileSdk、targetSdk、minSdk都按工程现状填,不要为了老 SDK 盲目升或降;multiDexEnabled在老项目里建议先打开,6.4.6 加上渠道实现后方法数容易顶到线。
android { // 这三个值按你工程当前基线填,不要直接复制示例数字 compileSdk 34 defaultConfig { minSdk 21 targetSdk 34 multiDexEnabled true manifestPlaceholders = [ UMENG_APPKEY: "替换为应用配置页里的 AppKey", UMENG_CHANNEL: "debug", FILE_PROVIDER_AUTHORITY: "${applicationId}.fileprovider" ] } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { // 先把 aar 放 app/libs,确认能编译再考虑抽到 library 模块 implementation files('libs/umeng_android_social_sdk_6.4.6_custom.aar') implementation 'androidx.core:core:1.12.0' // FileProvider 用,版本跟工程统一 }这段配置里真正需要解释的是manifestPlaceholders。AppKey 和渠道名不要写死在 Java 文件里,debug 和 release 分开配置,后面排查“debug 正常、release 失败”会省很多事。FILE_PROVIDER_AUTHORITY用${applicationId}.fileprovider拼出来,是为了避免多产品线安装在同一台机器上时 authority 冲突。multiDexEnabled只是先兜底,真正要不要开 MultiDex 还要看minSdk和构建结果。
环境组合上,我一般会遵循一个保守原则:工程本来就是 AGP 7.x,就不要为了这个 aar 硬升 AGP 8.x;工程已经是 AGP 8.x,先确认老 aar 有没有 namespace,再决定是补配置还是降 AGP。JDK 跟着 AGP 走,AGP 7.x 常用 JDK 11,AGP 8.x 常用 JDK 17,不要为了老 SDK 把 JDK 降到 8 以下,否则 Gradle 自身先出问题。AndroidX 和 support 二选一,不要在同一个工程里混用,FileProvider 的类名会因此不同。
提示:先把工程现有组合写进变更记录,再动分享 SDK。后面每出现一次编译错误,都能对照记录判断是不是版本组合引起的。
2.2 定制版包结构核对:classes.jar、res、assets、proguard
custom这个后缀不能只当成文件名差异。我见过的一个坑是:标准版里有某个渠道的实现类,定制包里被裁掉了,但工程里还留着对应的初始化代码和清单节点,编译期不报错,运行时才抛ClassNotFoundException。所以导入前先解包看结构,比直接跑真机更有效率。下面几条命令不需要改工程,只做只读核对。
# 1. 看 aar 顶层结构,确认 classes.jar、res、assets、AndroidManifest.xml 是否齐全 unzip -l umeng_android_social_sdk_6.4.6_custom.aar # 2. 直接看 AAR 内的清单,确认 uses-sdk、权限、provider、activity 声明 unzip -p umeng_android_social_sdk_6.4.6_custom.aar AndroidManifest.xml # 3. 把 classes.jar 抽出来,核对渠道实现类是否真的存在 unzip -p umeng_android_social_sdk_6.4.6_custom.aar classes.jar > /tmp/umeng-classes.jar jar tf /tmp/umeng-classes.jar | grep -i "socialize\|share" | head -50 # 4. 看资源名,提前发现 strings.xml、layout 命名冲突 unzip -l umeng_android_social_sdk_6.4.6_custom.aar | grep "res/"第一条命令看的是包结构,classes.jar是 Java 代码,res是资源和布局,assets里可能放渠道配置或证书类文件,AndroidManifest.xml决定合并清单。第二条命令要把uses-sdk里的minSdkVersion记下来,工程minSdk低于它会在合并时报错,高于它不一定能解决运行问题。第三条命令是为了核对渠道类,如果代码里配置了某个渠道,但jar tf结果里没有对应实现,就不要指望运行时能弹面板。第四条命令看资源前缀,老 SDK 的res命名比较通用,容易和工程里已有的strings.xml、layout撞名。
| 核对项 | 看什么 | 常见问题 |
|---|---|---|
classes.jar | 渠道实现类、回调类、ShareAction相关类 | 定制版裁掉渠道,代码仍在初始化 |
AndroidManifest.xml | 权限、uses-sdk、provider、activity | 合并后缺少渠道 Activity |
res/ | 布局、字符串、图片资源名 | 与工程资源重名,构建报资源冲突 |
assets/ | 渠道配置、证书、说明文件 | 漏拷贝导致初始化失败 |
proguard.txt | keep 规则、dontwarn | release 混淆后类被裁 |
表格里最容易被忽略的是proguard.txt。有些 aar 自带混淆规则,Gradle 会自动合并;定制包如果被重新打包过,这个文件可能缺失。导入后先在app/build/intermediates/merged_consumer_proguard_file一类目录里确认规则有没有进来,没有就手动补。不要只看 debug 能跑,release 才是混淆和签名问题集中爆发的地方。
2.3 版本选择取舍:AGP、AndroidX、JDK 的保守组合
这个 6.4.6 定制包最舒服的宿主工程,通常不是最新脚手架,而是已经稳定运行、依赖没有大改的老工程。我的取舍顺序是:先保 AGP 和 Gradle 不变,再保 AndroidX 不变,最后才调compileSdk。如果工程还在 support 库,不要为了一个分享 SDK 全量迁移 AndroidX,迁移成本远大于分享本身;反过来,工程已经是 AndroidX,也不要引入 support 版的FileProvider,否则会出现同名类冲突。
AGP 8 遇到老 aar 报 namespace 缺失时,不要照抄网上“在 aar 里补 namespace”的脚本。AAR 不是源码模块,android { namespace }对它不生效。常见做法是三条:让提供方补 namespace;把 AGP 降到 7.x 的最后一个稳定版本;或者把 aar 拆成源码模块重新维护。前两条更稳,第三条适合你确实要长期维护定制渠道的情况。JDK 不要单独降,Gradle 和 AGP 对 JDK 有最低要求,降错版本会先卡在构建脚本。
// gradle.properties 里这几个开关不要随手打开 android.useAndroidX=true android.enableJetifier=true // 老工程如果还有 support 依赖,enableJetifier 会拖慢构建,先确认是否真的需要android.useAndroidX=true表示工程走 AndroidX,android.enableJetifier=true会把旧 support 依赖重写为 AndroidX。后者不是越多越好,构建时间会涨,依赖冲突也更难查。我的习惯是:新加的分享 aar 如果本身不依赖 support,就不要为了它开 Jetifier;如果 aar 里确实引用了 support 类,再开,并且只开一个构建变体做验证。版本选择不是越新越安全,能让工程稳定出包的组合才是好组合。
3. 导入与工程配置:友盟分享 6.4.6 custom 的 aar、Manifest 和混淆
3.1 aar 导入与模块依赖:files 比 flatDir 更可控
导入 aar 有两种常见写法:implementation files('libs/xxx.aar')和implementation(name: 'xxx', ext: 'aar')配flatDir。我更倾向第一种,路径明确,依赖图里能直接看到文件,不会因为flatDir仓库顺序导致拉到同名旧包。分享代码如果放在app模块,直接implementation就行;如果放在library模块,并且app也要调用分享 API,就要用api把依赖传递出去,否则app编译时找不到ShareAction。
// library 模块:对外暴露分享 API 时用 api,不要用 implementation 藏起来 api files('libs/umeng_android_social_sdk_6.4.6_custom.aar') // app 模块:只自己用就 implementation implementation project(':share') implementation files('libs/umeng_android_social_sdk_6.4.6_custom.aar')这段依赖写法的关键是“谁暴露 API”。implementation不会把依赖传递给上层模块,api会。分享封装层如果只在自己的类里用ShareAction,上层只传字符串和图片路径,那就用implementation,封装更干净;如果上层要直接拿SHARE_MEDIA或UMShareListener,就必须api。导入后先跑一次./gradlew :app:dependencies --configuration debugRuntimeClasspath,确认依赖树里只有一份分享 SDK,没有旧版本残留。
注意:
libs目录下不要同时放标准版和 custom 版两个 aar。类名相同、资源相同,Gradle 可能都能编过,运行时先加载哪个全看玄学。
3.2 Manifest 合并:权限、FileProvider 和渠道 Activity
6.4.6 的清单合并是集成里最容易出问题的一步。AAR 自带的AndroidManifest.xml会和 app 的清单合并,权限、provider、activity 都会进最终包。定制版如果删了渠道,清单里对应的 activity 可能也没了,但你的代码还在配置那个渠道,运行时就会在打开面板或回调时崩。我的做法是先在app/build/intermediates/merged_manifest/debug/AndroidManifest.xml里搜一遍分享相关节点,确认 provider authority、activity 名称、权限都在,再跑真机。
<!-- app/src/main/AndroidManifest.xml --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- Android 13 以后读本地图片要按媒体权限处理,老权限只做兼容 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <application> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>权限部分不要一次性全加。INTERNET、ACCESS_NETWORK_STATE、ACCESS_WIFI_STATE是分享和网络请求常用项;存储权限要看 targetSdk 和分享图片来源。Android 13 以后读图片用READ_MEDIA_IMAGES,老版本用READ_EXTERNAL_STORAGE并加maxSdkVersion限制。FileProvider的authorities必须和代码里FileProvider.getUriForFile()的 authority 完全一致,差一个字符就会在分享本地图片时抛IllegalArgumentException。
<!-- app/src/main/res/xml/file_paths.xml --> <paths> <external-files-path name="umeng_share" path="share/" /> <cache-path name="umeng_cache" path="." /> </paths>file_paths.xml决定哪些目录可以暴露给其他应用。external-files-path适合放分享图片的专用目录,cache-path适合临时文件,但不要写path="."到根目录再配external-path,范围太大,审核和权限都容易出问题。我的习惯是给分享单独建一个share/目录,生成图片后马上用FileProvider转成content://URI,不再传file://。
3.3 混淆与资源冲突:release 包的 keep 规则要单独验
debug 能跑不代表 release 能跑,分享 SDK 尤其如此。混淆会把渠道实现类、回调类、反射用到的类裁掉或改名,表现是 release 包点分享无反应、回调不触发、或者直接ClassNotFoundException。aar 自带proguard.txt最好,没有就手动补。规则不要只 keep 主包,com.umeng.socialize下的渠道实现和回调也要保留。
# 分享 SDK 主包和子包一起保留,定制版渠道类可能被拆到不同包 -keep class com.umeng.** { *; } -keep interface com.umeng.** { *; } -keepclassmembers class com.umeng.** { *; } -keep class com.umeng.socialize.** { *; } -dontwarn com.umeng.** # 回调接口常被反射调用,保留实现类的方法签名 -keepclassmembers class * implements com.umeng.socialize.UMShareListener { public *; }这段规则里,-keep class com.umeng.**保留类和成员,-keepclassmembers保留成员不被裁剪,-dontwarn压掉找不到的可选依赖警告。不要为了省包体积只 keep 主包,渠道类一旦被裁,面板里可能连图标都出不来。验证方式是打一个 release 包,开minifyEnabled true,把UMConfigure.setLogEnabled(true)临时打开,点一次分享看日志里有没有类加载异常。
资源冲突则常见于strings.xml里的通用名字,比如umeng_socialize_*。如果工程里也有同名资源,Gradle 可能报Duplicate resources,或者运行时取到错误文案。先跑./gradlew :app:processDebugResources,看错误里指向哪个资源名,再决定是改名还是用tools:replace。不要一上来就全局tools:replace,会把 aar 里本来正确的配置也覆盖掉。
4. 初始化与渠道参数:友盟分享 6.4.6 custom 的 UMConfigure 与分享回调
4.1 Application 初始化:只做一次,多进程要拦住
初始化位置我一般放在Application.onCreate(),但会加一个主进程判断。多进程工程里,推送、后台服务各自跑在独立进程,Application会被多次创建,分享 SDK 如果重复初始化,日志里会出现重复注册,严重时还会影响渠道回调。UMConfigure.init()的五个参数分别是上下文、AppKey、渠道名、设备类型和 secret,secret 没有就传空字符串,不要传null赌 SDK 兼容。
public class App extends Application { @Override public void onCreate() { super.onCreate(); if (isMainProcess()) { // 日志只在 debug 打开,release 关掉,避免把 AppKey 打进日志 UMConfigure.setLogEnabled(BuildConfig.DEBUG); UMConfigure.init( this, BuildConfig.UMENG_APPKEY, BuildConfig.UMENG_CHANNEL, UMConfigure.DEVICE_TYPE_PHONE, "" ); } } private boolean isMainProcess() { String processName = getCurrentProcessName(); return getPackageName().equals(processName); } private String getCurrentProcessName() { // 老项目常见做法:读 /proc/self/cmdline,或使用 ActivityManager 兼容分支 return Application.getProcessName(); } }这段代码的关键是isMainProcess()和BuildConfig。AppKey 和渠道名从buildConfigField注入,debug 和 release 分开,不要把 release 的 AppKey 写进 debug 包。UMConfigure.setLogEnabled()只在 debug 开,release 关,日志里可能带设备信息和 AppKey 片段,上线包不要留。多进程判断用Application.getProcessName()需要 API 28 以上,老版本要加兼容分支,不能直接复制到低minSdk工程。
buildTypes { debug { buildConfigField "String", "UMENG_APPKEY", "\"debug 环境 AppKey\"" buildConfigField "String", "UMENG_CHANNEL", "\"debug\"" } release { buildConfigField "String", "UMENG_APPKEY", "\"release 环境 AppKey\"" buildConfigField "String", "UMENG_CHANNEL", "\"release\"" } }buildConfigField的第三个参数是带引号的字符串,少写转义会编译失败。渠道名不要随便填,应用配置页里如果有渠道维度,就按实际渠道填;没有就填一个能区分环境的固定值。初始化之后不要立刻弹分享面板,先让 SDK 完成注册,常见做法是在首页或分享按钮点击前再调ShareAction,不要在Application里做 UI 相关操作。
4.2 渠道参数配置:配置表驱动,不把渠道写死
定制版最忌讳把渠道枚举写死在代码里。标准版教程里常见的渠道初始化代码,到了 custom 包可能对应类已经被裁掉,编译能过是因为枚举还在,运行时才崩。我的做法是维护一张渠道配置表,只保留包内实际存在的渠道,初始化时按表过滤。下面示例用CHANNEL_X占位,实际枚举名以包内文档和classes.jar为准,不要照抄某一家的私有参数。
private static final Map<String, Boolean> CHANNEL_SWITCH = new HashMap<>(); static { // key 用包内文档里的渠道标识,value 表示是否启用 CHANNEL_SWITCH.put("CHANNEL_X", true); CHANNEL_SWITCH.put("CHANNEL_Y", false); } private SHARE_MEDIA[] getEnabledPlatforms() { List<SHARE_MEDIA> list = new ArrayList<>(); for (Map.Entry<String, Boolean> entry : CHANNEL_SWITCH.entrySet()) { if (!entry.getValue()) { continue; } SHARE_MEDIA media = SHARE_MEDIA.convertToEmun(entry.getKey()); if (media != null) { list.add(media); } } return list.toArray(new SHARE_MEDIA[0]); }CHANNEL_SWITCH是白名单,getEnabledPlatforms()只返回启用且 SDK 能识别的渠道。SHARE_MEDIA.convertToEmun()是常见转换方法,实际方法名以 6.4.6 包内 API 为准;如果找不到,就用SHARE_MEDIA.valueOf()加 try-catch,别让一个渠道配置错误拖垮整个面板。配置表可以放到assets或BuildConfig,但不要放在远程接口里动态下发,老 SDK 对未知渠道的处理不一定稳。
提示:定制包升级时,先对比新旧
classes.jar里渠道类清单,再改配置表。不要只看版本号相同就以为渠道没变。
4.3 分享调用与回调:onComplete 不等于成功
分享调用用ShareAction串起来:设置文本、图片、展示列表、回调,最后open()。文本分享和图片分享的路径不一样,图片要走UMImage和FileProvider,不能直接传file://。回调里onResult表示目标应用返回成功,onComplete只表示分享动作结束,不能把onComplete当成功提示,否则用户取消也会弹“分享成功”。
private void openSharePanel(String text, String imagePath) { ShareAction action = new ShareAction(this); action.withText(text); if (!TextUtils.isEmpty(imagePath)) { // 本地图片先确认 FileProvider 能生成 content:// URI action.withMedia(new UMImage(this, imagePath)); } action.setDisplayList(getEnabledPlatforms()); action.setCallback(new UMShareListener() { @Override public void onStart(SHARE_MEDIA platform) { Log.d("ShareTrace", "start: " + platform); } @Override public void onResult(SHARE_MEDIA platform) { // 这里才是目标应用返回成功 Log.d("ShareTrace", "result: " + platform); } @Override public void onError(SHARE_MEDIA platform, Throwable t) { Log.e("ShareTrace", "error: " + platform, t); } @Override public void onComplete(SHARE_MEDIA platform) { // 只代表动作结束,取消也会走到这里 Log.d("ShareTrace", "complete: " + platform); } }); action.open(); }setDisplayList()传的是数组,空数组会导致面板不弹,调用前先判空。UMImage的构造参数可以是本地路径、File或Bitmap,本地路径分享在 Android 10 以后要注意 URI 权限,FileProvider生成的 URI 要带FLAG_GRANT_READ_URI_PERMISSION。回调日志统一用ShareTrace标签,方便adb logcat过滤;onError里把Throwable打全,不要只打t.getMessage(),堆栈才是排查黑匣子。
5. 避坑与排查:友盟分享 6.4.6 custom 集成最常见的 5 个翻车点
5.1 现象:编译通过,点分享没有面板
现象是点击分享按钮后页面无反应,或者只闪一下,日志里没有ShareAction相关输出。原因通常是定制包把渠道实现裁掉了,但配置表里还开着对应渠道,setDisplayList()拿到的数组为空;也可能是初始化没执行,UMConfigure.init()被多进程判断拦住,当前进程不是主进程。解决顺序是先看classes.jar里有没有渠道类,再看getEnabledPlatforms()返回数量,最后在openSharePanel()前打一行日志确认初始化已完成。
我一般会加一段临时日志:Log.d("ShareTrace", "platforms=" + Arrays.toString(getEnabledPlatforms()));。如果数组为空,不要继续调open(),直接提示“当前包未包含可用分享渠道”。如果是初始化问题,把isMainProcess()的返回值打出来,确认当前进程名和包名一致。定制包不要拿标准版渠道清单硬套,白名单只开包内存在的渠道,这是最省返工的做法。
5.2 现象:面板弹出,选完渠道闪退
现象是面板能弹,点某个渠道后应用直接退出,日志里有FileUriExposedException、IllegalArgumentException或ActivityNotFoundException。原因分三类:本地图片还在用file://,Android 7.0 以后直接抛异常;FileProvider的 authority 和代码里不一致;渠道 Activity 在定制包里被删了,但面板里还显示。先看崩溃堆栈第一行,如果是 URI 暴露,就统一改FileProvider;如果是 Activity 找不到,就回清单合并结果里搜渠道 Activity。
FileProvider的排查要盯三个点:AndroidManifest.xml里的authorities、file_paths.xml里的目录、代码里getUriForFile()传的 authority。三者必须完全一致,包括大小写。图片目录要在file_paths.xml覆盖范围内,放在external-files-path下的share/就不要用cache-path去取。改完打 release 包再验一次,debug 的 URI 权限和 release 有时表现不同。
5.3 现象:debug 正常,release 分享失败
现象是 debug 包能弹面板、能回调,release 包点分享无反应或回调onError。原因常见于混淆裁掉渠道类、release 用了错误的 AppKey、签名和 Application 配置页不一致。解决时先关掉混淆打一个 release 包,如果关了混淆就正常,说明是 keep 规则问题;如果关了还失败,就看 AppKey 和签名。6.4.6 这类老 SDK 对签名校验比较敏感,包名和签名要和应用配置页一致。
混淆规则不要只写一行-keep class com.umeng.** { *; }就结束,回调接口的实现类、渠道配置类、反射用到的类都要覆盖。我一般会在 release 包里临时打开UMConfigure.setLogEnabled(true),跑一次分享,看日志里有没有ClassNotFoundException或NoSuchMethodException。确认后马上关掉日志,别把调试开关带上线。签名问题则用keytool打一下 release 签名的 MD5,和应用配置页核对,不要凭记忆。
5.4 现象:AGP 8 构建报 AAR 缺 namespace
现象是升级 AGP 8 后,构建直接报Namespace not specified,指向这个 6.4.6 定制 aar。原因是 AGP 8 要求所有模块声明 namespace,老 aar 没有这个字段。解决不要照抄“在 aar 的build.gradle里加 namespace”的脚本,aar 不是源码模块,改了也不生效。稳妥做法是让提供方补 namespace,或者把 AGP 降到 7.x 的稳定版本;如果必须留在 AGP 8,就把 aar 拆成源码模块重新维护,成本更高但可控。
我一般会先确认报错来自哪个任务:processDebugManifest还是mergeDebugResources。如果是 namespace,降 AGP 最快;如果是资源冲突,就不要降 AGP,回到 3.3 节处理资源名。降 AGP 前先看 Gradle 版本是否匹配,AGP 7.x 配 Gradle 7.x,不要只降一边。降完清一次.gradle和build目录,避免缓存把旧错误带进来。
5.5 现象:图片分享到目标应用显示空白
现象是文本分享正常,图片分享过去只有文字或空白图。原因通常是 URI 权限没授出去、图片路径不在FileProvider范围内、或者目标应用读不到content://。解决时先确认UMImage收到的是content://而不是file://,再确认Intent里带了FLAG_GRANT_READ_URI_PERMISSION。如果是自定义分享回调,检查有没有手动调grantUriPermission()。
图片目录我一般固定为getExternalFilesDir("share"),生成图片后马上用FileProvider.getUriForFile()转 URI,分享完再删临时文件。不要把图片放sdcard根目录再申请存储权限,Android 10 以后分区存储会让路径失效。验证时用系统相册或文件管理器打开同一个 URI,如果能打开,说明 URI 本身没问题,问题在目标应用接收参数;如果打不开,回到file_paths.xml和 authority 查。
6. 装完怎么验证:友盟分享 6.4.6 custom 的分享链路自检
验证不要只点一次“分享”看有没有弹窗,我一般按“初始化、面板、回调、release”四段走。第一段看初始化日志,确认UMConfigure.init()只执行一次,且当前进程是主进程。第二段看面板渠道数量,和classes.jar里的渠道类清单对得上。第三段看回调,onResult和onComplete分开打点,取消操作也要走一遍。第四段打 release 包,开混淆,重复前三段。
# 1. 清日志后启动应用,过滤分享初始化 adb logcat -c adb logcat | grep -i "UMConfigure\|ShareTrace" # 2. 检查合并后的清单里 provider authority 是否正确 grep -n "fileprovider\|umeng" app/build/intermediates/merged_manifest/debug/AndroidManifest.xml # 3. 看 release 依赖树里是否只有一份分享 SDK ./gradlew :app:dependencies --configuration releaseRuntimeClasspath | grep -i umeng # 4. 安装 release 包后重复分享,确认混淆规则生效 adb install -r app/build/outputs/apk/release/app-release.apkadb logcat过滤时不要只看UMeng大写,老 SDK 日志标签大小写不统一,grep -i更稳。合并清单里重点看provider的authorities和applicationId是否一致,多产品线工程尤其容易在这里翻车。依赖树里如果出现两个版本的分享 SDK,先排掉旧包再验分享,否则日志会骗人。release 包安装前先卸载 debug 包,避免签名不同导致安装失败。
| 验证项 | 通过标准 | 失败先看 |
|---|---|---|
| 初始化 | 主进程只打一次初始化日志 | 多进程判断、Application 注册 |
| 面板 | 渠道数量与包内类清单一致 | 白名单、classes.jar |
| 文本分享 | onResult回调触发 | AppKey、网络、渠道配置 |
| 图片分享 | 目标应用能显示图片 | FileProvider、URI 权限 |
| release | 混淆后仍能弹面板和回调 | keep 规则、签名、AppKey |
这套 6.4.6 custom 包我按目录整理过,拿到后先跑第 2 章的unzip核对,再按第 3 章顺序改清单和混淆,不要直接覆盖libs里的旧包。从那以后我每次集成老分享 SDK,都强制走一遍“解包看清单、白名单只开存在的渠道、release 包单独验回调”的流程,少一次都容易在真机上返工。希望帮到你。
本文还有配套的精品资源,点击获取