Closed 790396054 closed 6 months ago
虽然你写了好多字,但是很难看懂啊。因为我们平常不在同一个工作的上下文里。为什么宁可写这么多字描述,也不把代码放上来呢?你就说clone这个分支,跑起来点哪,断点第几行,这个变量的值预期是什么,实际是什么。
更好的是直接扩展一个自动化测试用例,然后就什么也不用说了。代码里现有一个TestFileProviderActivity
,可以基于它写一个。
大神好,其实楼主说的就是7.0以上FileProvider的适配和替换问题:
1、没有看到需要在宿主里面注册FileProvider的操作,以及不知道res>xm>filepath.xml文件指定的存储目录结构是怎样的; 如果插件里面用到了uri怎么办,比如调用安装页面,存储照片; 目前测试下来是都找不到对应的authority和存储路径;
2、第二个问题就是楼主描述不清楚的问题,如下源码所示,为啥框架要把沙盒的存储目录都改成:”原路径+插件名字“ 的路径,这样会导致filepath.xml里面写的路径和实际存储的对不上;
此处采自框架源码: com.tencent.shadow.core.runtime.SubDirContextThemeWrapper.java
@Override
public File getDataDir() {
if (getSubDirName() == null) {
return super.getDataDir();
}
synchronized (mSync) {
if (mDataDir == null) {
mDataDir = new File(super.getDataDir(), getSubDirName());
}
return ensurePrivateDirExists(mDataDir);
}
}
@Override
public File getFilesDir() {
if (getSubDirName() == null) {
return super.getFilesDir();
}
synchronized (mSync) {
if (mFilesDir == null) {
mFilesDir = new File(super.getFilesDir(), getSubDirName());
}
return ensurePrivateDirExists(mFilesDir);
}
}
备注:getSubDirName()为获取到的插件名字
为啥框架要把沙盒的存储目录都改成:”原路径+插件名字“ 的路径
这是因为要避免宿主以及多个插件之间文件路径冲突。这个路径应该是由businessName
字段决定的。如果为空,应该就不会修改路径了,相当于插件复用宿主的根目录。
另外如果确实有问题,建议修改sample中的TestFileProviderActivity
复现问题,然后把代码push上来看看。
TestFileProviderActivity的使用方式是没有问题的,因为它注册的是:android.support.v4.content.FileProvider 注册的路径是:包名 + general_cases.fileprovider,在调用的时候找的也是:包名 + general_cases.fileprovider <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.general_cases.fileprovider"
问题: 如果我插件里面有一个:a.b.c.FileProvider继承了support包的FileProvider,使用了其它的路径(android:authorities) 例子:比如插件的清单包含这样的一个provider: <provider android:name="a.b.c.FileProvider" android:authorities="${applicationId}.a.b.c"
这个时候宿主里面并没有注册这个,实际运行会找不到这个contentUri;
猜测的结论: 我是不是可以理解为:如果插件要使用自定义的FileProvider,只能使用support或者androidX包里面的,而且只能使用一个路径(事先和宿主约定好:android:authorities),动态编译并没有帮我替换这些东西
问题: 如果我插件里面有一个:a.b.c.FileProvider继承了support包的FileProvider,使用了其它的路径(android:authorities) 例子:比如插件的清单包含这样的一个provider: <provider android:name="a.b.c.FileProvider" android:authorities="${applicationId}.a.b.c"
看不懂你的a.b.c.FileProvider
和android.support.v4.content.FileProvider
有什么区别。你不用说“如果”怎么样,你就直接把复现代码push上来,能复现就行了。
我们的插件使用了 takePhoto 这个拍照库,https://github.com/crazycodeboy/TakePhoto。 过程是这样的: 1.宿主注册了一个 provider
3.插件注册了provider
4.打开系统相机的代码:
打开拍照,能正常拍照。
5.得到照片时,发现 第 4 步的 contentUri 值是
就是 authority 值是 com.tencent.shadow.sample.host.dynamic.fileprovider 这个是宿主中的 authority,现在的问题是我想在插件中把这个值变为
就是把 authority 变为 插件中注册是 com.tencent.shadow.sample.host.fileprovider 这个值。 我的写法如下:
结果是第一行代码是
符合预期。
而第二行代码结果是
前面的 authority 又变为宿主的值了。 不知道为什么 Uri.parse 这个方法执行完,值就变化了。
我在插件中看 ShadowContentProviderDelegate 类的 openFile 方法,99 行
调用了 val pluginUri = mProviderManager.convert2PluginUri(uri) 行。而这个值就能把宿主的 Authority 变为插件的 Authority。 而我看 convert2PluginUri 这个方法的实现也是 Uri.Parse 方法。
最后,我的期望是 我也想把宿主的 Authority 变为插件的 Authority。这样我的业务修改最小。 感谢阅读