Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

插件里ContentProvider不能使用 #253

Closed
kkmike999 opened this issue Aug 6, 2016 · 8 comments
Closed

插件里ContentProvider不能使用 #253

kkmike999 opened this issue Aug 6, 2016 · 8 comments

Comments

@kkmike999
Copy link

kkmike999 commented Aug 6, 2016

目录结构

  • app
  • app.main
  • app.main2

app.main2配置了ContentProvider

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.mysmall.app.main2">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="AppMain2"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity2">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <provider
            android:name=".BeanProvider"
            android:exported="true"
            android:authorities="com.example.mysmall.app.main2.BeanProvider"/>

        <activity android:name=".ActivityC">
        </activity>
    </application>

</manifest>

app.main2MainActivity2获取不到ContentProvider

package com.example.mysmall.app.main2;

public class MainActivity2 extends AppCompatActivity {
    private static final String AUTHORITY = "com.example.mysmall.app.main2.BeanProvider";

    @Override
    protected void onCreate(Bundle savedInstanceState) { ... }

    public void onProviderClick(View view) {
        ContentProviderClient client  = getContentResolver().acquireContentProviderClient(AUTHORITY);
        ContentProvider       provider = client.getLocalContentProvider();

        // provider == null

    }
}

我本来想在app.main和宿主获取app.main2配置的ContentProvider的,用于解决插件间通讯问题。不知道以后Small能不能支持?

@galenlin

@kkmike999 kkmike999 changed the title 组件ContentProvider不能使用 插件里ContentProvider不能使用 Aug 6, 2016
@galenlin
Copy link
Member

galenlin commented Aug 9, 2016

目前插件manifest只支持注册Activity,其他系统组件需要在宿主进行注册。

@kkmike999
Copy link
Author

@galenlin 那以后有没计划支持插件里注册content provider?

@galenlin
Copy link
Member

galenlin commented Aug 9, 2016

不会做到Small核心库里。后期可能考虑以某种方式向外导接口给用户自己扩展。

@kkmike999
Copy link
Author

@galenlin 因为android studio可以在依赖的module声明provider的,Small不可以的话,有点奇怪。或者在bundle.json 里配置也可以

@galenlin
Copy link
Member

galenlin commented Aug 9, 2016

@kkmike999 现在的问题是运行时的处理,动态注册Provider需要增加一系列的hook操作。会带来一些成本,根据二八原则,框架应该集中精力满足80%的需求,并做到极致。

所以目前我的建议是在宿主的manifest去注册你的Provider就可以了,代码实现可以放到插件里。

@kkmike999
Copy link
Author

kkmike999 commented Aug 12, 2016

@galenlin 请问在宿主如何注册插件的Provider?因为Provider代码写在插件,所以app/AndroidManifest.xml不能引用插件Provider.

<provider
            android:name="com.small.provider.app.main.AppMainProvider"
            android:authorities="com.small.provider.app.main.AppMainProvider"/>

运行时报错:


 Process: com.small.provider, PID: 29125
 java.lang.RuntimeException: Unable to get provider com.small.provider.app.main.AppMainProvider: java.lang.ClassNotFoundException: Didn't find class "com.small.provider.app.main.AppMainProvider" on path: DexPathList[[zip file "/data/app/com.small.provider-1/base.apk"],nativeLibraryDirectories=[/data/app/com.small.provider-1/lib/arm, /vendor/lib, /system/lib]]
     at android.app.ActivityThread.installProvider(ActivityThread.java:5037)
     at android.app.ActivityThread.installContentProviders(ActivityThread.java:4629)
     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4569)
     at android.app.ActivityThread.access$1500(ActivityThread.java:154)
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1380)
     at android.os.Handler.dispatchMessage(Handler.java:102)
     at android.os.Looper.loop(Looper.java:135)
     at android.app.ActivityThread.main(ActivityThread.java:5298)
     at java.lang.reflect.Method.invoke(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:372)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:910)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:705)

  Caused by: java.lang.ClassNotFoundException: Didn't find class "com.small.provider.app.main.AppMainProvider" on path: DexPathList[[zip file "/data/app/com.small.provider-1/base.apk"],nativeLibraryDirectories=[/data/app/com.small.provider-1/lib/arm, /vendor/lib, /system/lib]]
     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
     at android.app.ActivityThread.installProvider(ActivityThread.java:5022)
     at android.app.ActivityThread.installContentProviders(ActivityThread.java:4629) 
     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4569) 
     at android.app.ActivityThread.access$1500(ActivityThread.java:154) 
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1380) 
     at android.os.Handler.dispatchMessage(Handler.java:102) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5298) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:372) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:910) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:705) 

    Suppressed: java.lang.ClassNotFoundException: com.small.provider.app.main.AppMainProvider
     at java.lang.Class.classForName(Native Method)
     at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
     at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
            ... 13 more
  Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

@galenlin
Copy link
Member

从你的log来看,插件没有被加载:

Didn't find class "com.small.provider.app.main.AppMainProvider" on path: DexPathList[[zip file "/data/app/com.small.provider-1/base.apk"], ...

如果有插件,这里的DexPathList不只一个的。

@kkmike999
Copy link
Author

kkmike999 commented Aug 12, 2016

@galenlin 我在SmappApp的onCreate()时才Small.setUpAndroidManifest.xml应该在onCreate前就被解析(仅仅猜测),所以在AndroidManifest.xml声明provider就会报这错。

不过我找到了动态加载Provider的方法:

public void onBtnAppMainProviderClick(View view) throws ClassNotFoundException {
        Class clazz = Class.forName("com.small.provider.app.main.AppMainProvider");

        ProviderInfo info = new ProviderInfo();
        info.authority = clazz.getName();
        info.applicationInfo = applicationInfo;
        info.processName = "com.small.provider";
        info.name = clazz.getName();
        info.packageName = clazz.getPackage().getName();
        info.enabled = true;

        installProvider(this, Arrays.asList(info));
}

protected void installProvider(Context context, ProviderInfo providerInfo) {
        try {
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");

            Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
            Object currentActivityThread       = currentActivityThreadMethod.invoke(null);
            Method installProvidersMethod      = activityThreadClass.getDeclaredMethod("installContentProviders", Context.class, List.class);
            installProvidersMethod.setAccessible(true);
            installProvidersMethod.invoke(currentActivityThread, context, infos);
        } catch (Exception e) {
            e.printStackTrace();
        }
}

我觉得Small应该提供动态注册provider方法,只要提供provider packageName+className。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants