Android application with camera2 library crash on

2020-04-23 02:40发布

问题:

I use androidx.camera.camera2 library in my application. This library for SDK 21 and greater. But i want allow users start application for SDK 19 without camera2 support. I check SDK version in my code, but application crash on start. Can i exclude camera2 from dependencies for old SDK?

05-30 12:13:42.318 2000-2000/com.myapp.android E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.android, PID: 2000
java.lang.NoClassDefFoundError: android.util.Size
    at androidx.camera.camera2.impl.Camera2DeviceSurfaceManager.<clinit>(Camera2DeviceSurfaceManager.java:53)
    at androidx.camera.camera2.Camera2AppConfig.create(Camera2AppConfig.java:58)
    at androidx.camera.camera2.impl.Camera2Initializer.onCreate(Camera2Initializer.java:44)
    at android.content.ContentProvider.attachInfo(ContentProvider.java:1591)
    at android.content.ContentProvider.attachInfo(ContentProvider.java:1562)
    at android.app.ActivityThread.installProvider(ActivityThread.java:4790)
    at android.app.ActivityThread.installContentProviders(ActivityThread.java:4385)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4325)
    at android.app.ActivityThread.access$1500(ActivityThread.java:135)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5017)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
    at dalvik.system.NativeStart.main(Native Method)

回答1:

I recently stumbled into the same issue. Diving deep into the CameraX code I found that CameraX is initialized in app startup through a content provider. Here is the content provider code where CameraX is being initialized.

public final class Camera2Initializer extends ContentProvider {
    private static final String TAG = "Camera2Initializer";
    @Override
    public boolean onCreate() {
        Log.d(TAG, "CameraX initializing with Camera2 ...");
        CameraX.init(getContext(), Camera2AppConfig.create(getContext()));
        return false;
    }
}

Im not very familiar with content providers but my first taught was, this is add at the manifest level? And indeed I was right. Looking at there manifest I found this

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="androidx.camera.camera2">
    <application>
        <provider
            android:name=".Camera2Initializer"
            android:authorities="${applicationId}.camerax-init"
            android:exported="false"
            android:initOrder="100"
            android:multiprocess="true" />
    </application>
</manifest>

There manifest gets merged into ours which will include this content provider which in the other hand initializes CameraX, we want to avoid this. So one possible way of doing so is creating our own empty content provider and adding it to our manifest with the same name. This will override there content provider. You can look into https://developer.android.com/studio/build/manifest-merge for more detail about manifest merging.

So now with there content provider overriden hopefully you can call CameraX.init(getContext(), Camera2AppConfig.create(getContext())); only when the feature gets called and not on app startup.

Im hoping this gets fixed in later versions and allows us to initialize cameraX when we want to.