Android URL转Bitmap报MalformedURLException无协议错误解决
问题根因
你抛出的no protocol: 异常后面没有拼接任何URL内容,核心原因就是执行new URL(image_url)时,传入的image_url是空字符串,根本不是合法的URL入参。
你硬编码固定链接可以正常运行,已经证明后续的Bitmap解码、系统壁纸设置逻辑完全没问题,和三个图片源的地址合法性、UTF-8编码没有任何关系。
之前你尝试的对整个URL做URLEncoder.encode的方案本身就是错误用法:这个方法是用来编码URL参数中的特殊字符的,对整个完整URL编码会把https://里的冒号、斜杠都转义,反而会生成非法URL,根本解决不了问题。
修复步骤
- 先排查Firebase取值的时序问题
90%的概率是你没有等待Firebase异步拉取数据完成,就提前触发了壁纸设置逻辑,此时image_url还没被赋值,默认是空值。
先加一行日志确认变量实际值:
如果日志打出来取值为空、长度为0,就必须调整代码逻辑:等Firebase数据回调拿到有效URL字符串之后,再启动壁纸设置的后台任务,不要提前执行后续逻辑。Log.d("wallpaper_check", "当前image_url取值:[" + image_url + "], 长度:" + (image_url == null ? -1 : image_url.trim().length())); - 增加URL合法性前置校验
拿到image_url之后不要直接传入URL构造方法,先做基础校验,过滤非法值:// 空值直接返回失败,让Worker后续重试 if (image_url == null || image_url.trim().isEmpty()) { Log.e("wallpaper_check", "URL为空,终止本次设置"); return Result.failure(); } // 校验协议头,避免拿到缺省http/https的地址 if (!image_url.startsWith("http://") && !image_url.startsWith("https://")) { Log.e("wallpaper_check", "URL缺少协议头:" + image_url); return Result.failure(); } - 移除错误的全URL编码逻辑
你给出的Pexels、Pixabay、Unsplash三类示例URL本身就是经过合法编码的可直接访问地址,不需要对整个字符串做URLEncoder编码。如果后续碰到URL参数带特殊字符的场景,只需要单独编码参数值部分,不要对协议头、域名、路径做转义。 - 优化网络拉取的稳定性(可选)
你当前直接调用openConnection的写法没有设置超时,弱网下容易长时间卡住,建议补全超时配置,用完及时断开连接:HttpURLConnection conn = (HttpURLConnection) new URL(image_url).openConnection(); conn.setConnectTimeout(10000); // 10秒连接超时 conn.setReadTimeout(15000); // 15秒读取超时 Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream()); conn.disconnect(); WallpaperManager myWallpaperManager = WallpaperManager.getInstance(getApplicationContext()); myWallpaperManager.setBitmap(bitmap, null, false, WallpaperManager.FLAG_SYSTEM);
注意事项
- 确认已经在AndroidManifest中声明
android.permission.INTERNET权限,你硬编码URL能正常运行说明权限已经配置,可跳过此项检查。 - WorkManager的
doWork()方法本身运行在后台线程,不要把网络、Bitmap解码逻辑切到主线程执行,避免触发NetworkOnMainThreadException。
内容的提问来源于stack exchange,提问作者Akshit Bhandari
相关产品推荐
相关产品推荐

