You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动