Kivy用jnius调用Intent选图库图片闪退报No running App found错误求助
问题排查与修复方案
闪退根本原因
on_activity_result回调函数中引用了未定义的变量:currentActivity、layout、webview,调用不存在的变量直接触发未捕获异常,导致Kivy主循环崩溃退出,最终抛出NoneType无run属性的报错Push函数定义要求传入callback参数,但是按钮on_press绑定时没有传入对应参数,实际调用时默认传入的是按钮实例,后续调用callback(None)会出现类型错误- 每次点击按钮都会重复绑定
on_activity_result事件,多次绑定会导致回调被重复触发,引发逻辑混乱 - 未申请Android读取存储的动态权限,Android 6.0+版本访问系统图库内容必须先申请
READ_EXTERNAL_STORAGE权限,否则访问内容提供器时会崩溃
修复后的完整代码
from android.runnable import run_on_ui_thread as run_thread from jnius import autoclass, cast from kivy.uix.gridlayout import GridLayout from kivy.uix.button import Button from kivy.app import App from android import activity as act from android.permissions import request_permissions, Permission # 提前申请读取存储权限 request_permissions([Permission.READ_EXTERNAL_STORAGE]) Uri = autoclass('android.net.Uri') MediaStore_Images_Media_DATA = "_data" RESULT_LOAD_IMAGE = 1 PythonActivity = autoclass('org.kivy.android.PythonActivity') Intent = autoclass('android.content.Intent') Activity = autoclass('android.app.Activity') # 全局只绑定一次activity结果回调 def on_activity_result(request_code, result_code, intent): if request_code != RESULT_LOAD_IMAGE: return if result_code == Activity.RESULT_CANCELED: print("用户取消选择") return if result_code != Activity.RESULT_OK: print(f"未知返回码:{result_code}") return activity = cast('android.app.Activity', PythonActivity.mActivity) selectedImage = intent.getData() filePathColumn = [MediaStore_Images_Media_DATA] cursor = activity.getContentResolver().query(selectedImage, filePathColumn, None, None, None) cursor.moveToFirst() columnIndex = cursor.getColumnIndex(filePathColumn[0]) picturePath = cursor.getString(columnIndex) cursor.close() print(f"选中的图片路径:{picturePath}") act.bind(on_activity_result=on_activity_result) @run_thread def push(instance): activity1 = cast('android.app.Activity', PythonActivity.mActivity) intent= Intent(Intent.ACTION_GET_CONTENT) intent.addCategory(Intent.CATEGORY_OPENABLE) intent.setType("image/*") activity1.startActivityForResult(intent, RESULT_LOAD_IMAGE) class GalleryApp(App): def build(self): m=GridLayout(cols=1,rows=1) d=GridLayout(cols=1,rows=1) m.add_widget(d) b=Button(text="打开图库") b.bind(on_press=push) d.add_widget(b) return m if __name__ == "__main__": GalleryApp().run()
额外注意事项
- 原代码中操作
layout、webview的逻辑因为没有对应的变量定义,已经删除,如果确实需要操作WebView,需要先正确实例化对应对象再操作 - buildozer.spec文件中需要添加权限声明:
android.permissions = READ_EXTERNAL_STORAGE
内容的提问来源于stack exchange,提问作者koushik
相关产品推荐
相关产品推荐

