{"record":{"id":"13b9d28d5891fb06","repo":"Tencent/QMUI_Android","slug":"no-qmuimediaphotoproviderfactory-is-provided","errorCode":null,"errorMessage":"no QMUIMediaPhotoProviderFactory is provided.","messagePattern":"no QMUIMediaPhotoProviderFactory is provided\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"photo/src/main/java/com/qmuiteam/photo/vm/QMUIPhotoPickerViewModel.kt","lineNumber":57,"sourceCode":"    var prevScene: QMUIPhotoPickerScene? = null\n        private set\n\n    private val _photoPickerDataFlow = MutableStateFlow(QMUIPhotoPickerData(QMUIPhotoPickerLoadState.permissionChecking, null))\n    val photoPickerDataFlow = _photoPickerDataFlow.asStateFlow()\n\n    private val _pickedMap = mutableMapOf<Long, QMUIMediaPhotoVO>()\n    private val _pickedListFlow = MutableStateFlow<List<Long>>(emptyList())\n    val pickedListFlow = _pickedListFlow.asStateFlow()\n\n    private val _pickedCountFlow = MutableStateFlow(0)\n    val pickedCountFlow = _pickedCountFlow.asStateFlow()\n\n    private val _isOriginOpenFlow = MutableStateFlow(false)\n    val isOriginOpenFlow = _isOriginOpenFlow.asStateFlow()\n\n    init {\n        val photoProviderFactoryClsName =\n            state.get<String>(QMUI_PHOTO_PROVIDER_FACTORY) ?: throw RuntimeException(\"no QMUIMediaPhotoProviderFactory is provided.\")\n        photoProviderFactory = Class.forName(photoProviderFactoryClsName).newInstance() as QMUIMediaPhotoProviderFactory\n    }\n\n    fun updateScene(scene: QMUIPhotoPickerScene) {\n        prevScene = _photoPickerSceneFlow.value\n        _photoPickerSceneFlow.value = scene\n    }\n\n    fun permissionDenied() {\n        _photoPickerDataFlow.value = QMUIPhotoPickerData(QMUIPhotoPickerLoadState.permissionDenied, null)\n    }\n\n    fun permissionGranted() {\n        _photoPickerDataFlow.value = QMUIPhotoPickerData(QMUIPhotoPickerLoadState.dataLoading, null)\n        viewModelScope.launch {\n            try {\n                val data = withContext(Dispatchers.IO) {\n                    dataProvider.provide(application, supportedMimeTypes).map { bucket ->","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/photo/src/main/java/com/qmuiteam/photo/vm/QMUIPhotoPickerViewModel.kt#L39-L75","documentation":"QMUIPhotoPickerViewModel's init block reads the QMUI_PHOTO_PROVIDER_FACTORY key from the SavedStateHandle. If absent, it throws RuntimeException(\"no QMUIMediaPhotoProviderFactory is provided.\") because the picker cannot instantiate its photo provider without knowing the factory class name. It then reflectively loads and instantiates that class.","triggerScenarios":"Launching QMUIPhotoPickerActivity without putting a String under QMUI_PHOTO_PROVIDER_FACTORY into the launch Intent extras; the SavedStateHandle lookup returns null.","commonSituations":"Starting the picker activity directly without the required extra; key renamed between library versions; building the Intent manually instead of via the provided launcher helper; proguard/reflection failing later (Class.forName) after missing key check passes.","solutions":["Put the factory class name extra into the launch Intent: intent.putExtra(QMUI_PHOTO_PROVIDER_FACTORY, YourFactory::class.java.name).","Use the library's picker builder/launcher helper which sets the extra for you.","Ensure the factory class is instantiable (public, no-arg constructor) and not stripped by ProGuard (add keep rule)."],"exampleFix":"// before\nstartActivity(Intent(context, QMUIPhotoPickerActivity::class.java)) // throws\n// after\nstartActivity(Intent(context, QMUIPhotoPickerActivity::class.java).putExtra(QMUI_PHOTO_PROVIDER_FACTORY, MyPhotoProviderFactory::class.java.name))","handlingStrategy":"validation","validationCode":"val intent = Intent(context, QMUIPhotoPickerActivity::class.java)\nrequire(intent.hasExtra(QMUI_PHOTO_PROVIDER_FACTORY)) { \"QMUI_PHOTO_PROVIDER_FACTORY extra required\" }","typeGuard":null,"tryCatchPattern":"try { launcher.launch(intent) } catch (e: RuntimeException) { Log.e(TAG, \"picker misconfigured\", e) }","preventionTips":["Always build the picker Intent via the library's helper","Set QMUI_PHOTO_PROVIDER_FACTORY to a public class with a no-arg constructor","Add ProGuard keep rules for the factory class"],"tags":["android","viewmodel","photo-picker","missing-extra","reflection"],"backgroundTag":"missing-required-argument","analyzedSha":"026e7d486677d6593a96689cd590ec3561176717","analyzedAt":"2026-09-06T13:32:24.816Z","contentChangedAt":"2026-09-06T13:32:24.816Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}