Kivy应用手机端调用API出现urllib连接错误求助
解决Kivy移动端requests连接失败的问题
嘿,我看你遇到的是Kivy应用在手机上的网络连接问题——PC端正常,手机端报No address associated with hostname,这个问题我之前帮朋友排查过,大概率是网络权限、域名解析或者移动端特有的文件存储/请求配置导致的,下面给你具体的解决步骤:
1. 先检查应用的网络权限(最容易忽略!)
在Android上,应用默认没有网络访问权限,你打包APK的时候必须手动声明:
- 如果你用Buildozer打包,打开
buildozer.spec,找到android.permissions这一行,改成:android.permissions = INTERNET - 用其他工具打包的话,也要确保
AndroidManifest.xml里加了<uses-permission android:name="android.permission.INTERNET" />这行权限声明。
2. 验证手机网络能否访问目标地址
先在手机浏览器里打开 https://kitsu.io/api/edge/anime?filter[text]=naruto,看看能不能正常加载:
- 如果浏览器也打不开,那是手机网络的问题——比如DNS解析失败,试试切换WiFi/移动数据,或者手动设置公共DNS(比如8.8.8.8)。
- 如果浏览器能访问,但应用不行,那就是代码里的请求配置或者移动端的网络适配问题,继续往下看。
3. 优化你的requests请求代码
你的代码有几个可以优化的地方,适配移动端环境:
def Anime_Search(self): # 统一请求头,用更贴近移动端的User-Agent headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36', 'Accept': 'application/vnd.api+json', 'Content-Type': 'application/vnd.api+json' } # 对搜索关键词做URL编码,避免特殊字符破坏URL import urllib.parse encoded_anime = urllib.parse.quote(str(anime2)) url = f'https://kitsu.io/api/edge/anime?filter[text]={encoded_anime}' try: # 增加超时时间,移动端网络不稳定,默认超时可能太短 request = requests.get(url, headers=headers, timeout=10) request.raise_for_status() # 主动抛出HTTP错误,方便调试 anime = request.json() poster = anime['data'][0]['attributes']['posterImage']['medium'] r = requests.get(poster, stream=True, headers=headers, timeout=10) r.raise_for_status() # 重点!移动端不能直接写根目录,要写到应用私有存储路径 from kivy.utils import platform import os if platform == 'android': from android.storage import app_storage_path save_path = os.path.join(app_storage_path(), 'img.jpg') else: save_path = 'img.jpg' with open(save_path, 'wb') as f: shutil.copyfileobj(r.raw, f) except requests.exceptions.RequestException as e: print(f"请求出错啦: {str(e)}") # 这里可以给用户弹个提示,比如用Kivy的Label或者Popup
这里的关键点:
- 给搜索关键词做URL编码,避免像空格、中文这类特殊字符导致URL无效。
- 增加超时时间,移动端网络波动大,默认的超时时间可能不够。
- 修复文件存储路径:Android应用没有权限写入根目录,必须用
app_storage_path()获取合法的私有存储路径。
4. 备选方案:改用Kivy自带的UrlRequest
如果requests在移动端还是有兼容性问题,可以试试Kivy原生的UrlRequest,它是专门为移动端优化的,还能减少APK体积(不用打包requests库):
from kivy.network.urlrequest import UrlRequest import os import shutil def Anime_Search(self): # 处理搜索结果的回调 def on_search_success(req, result): poster_url = result['data'][0]['attributes']['posterImage']['medium'] # 处理海报下载的回调 def on_poster_success(req_poster, poster_data): from kivy.utils import platform if platform == 'android': from android.storage import app_storage_path save_path = os.path.join(app_storage_path(), 'img.jpg') else: save_path = 'img.jpg' with open(save_path, 'wb') as f: f.write(poster_data) UrlRequest(poster_url, on_success=on_poster_success, headers={'User-Agent': 'Mozilla/5.0'}) headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36', 'Accept': 'application/vnd.api+json', 'Content-Type': 'application/vnd.api+json' } import urllib.parse encoded_anime = urllib.parse.quote(str(anime2)) url = f'https://kitsu.io/api/edge/anime?filter[text]={encoded_anime}' UrlRequest(url, on_success=on_search_success, headers=headers)
建议你先从检查网络权限开始,这是90%以上移动端网络问题的根源,然后再调整代码里的路径和请求配置,应该就能解决问题啦!
内容的提问来源于stack exchange,提问作者SenseiB




