当前位置: 首页 > news >正文

Android Url的一些常见处理

日常开发的时候,会遇到各种各样的Url.这里就总结一些常见的Url遇到的一些问题,以及对应的处理方式

常见问题

  • 参数问题
  • 重定向问题
  • Url长度问题
  • Url传递过程中编码问题
1.Url 参数处理

1.1 获取Url 指定参数的值

/** * 获取Url的原来参数值 */ fun getQueryParameterValue(url: String, key: String): String? { if (TextUtils.isEmpty(url) || TextUtils.isEmpty(key)) return url var uri = Uri.parse(url) if (uri.isOpaque()) { return url } //利用Map的唯一性拼接参数 var parameterMap = getParameterMap(url) return parameterMap.get(key) } /** * 获取Url参数的值(Decode之后的) * * getQueryParameter() 方法是默认Decode的 * */ fun getQueryParameterDecodeValue(url: String, key: String): String? { if (TextUtils.isEmpty(url) || TextUtils.isEmpty(key)) return "" var uri = Uri.parse(url) if (uri.isOpaque()) { return "" } else { return Uri.parse(url).getQueryParameter(key) } } /** * 把url 的参数转为Map存储 */ private fun getParameterMap( url: String ): HashMap<String, String> { var map: HashMap<String, String> = HashMap<String, String>() // 参数名字的列表 var parameter = Uri.parse(url).queryParameterNames parameter.forEach { if (getQueryParameterDecodeValue(url, it) != null) map.put(it, getQueryParameterDecodeValue(url, it)!!) } return map }

1.2 添加和删除指定参数

/** * 删除Encode 的参数 */ fun deleteQueryParameterDecodeValue(url: String, key: String): String { if (TextUtils.isEmpty(url) || TextUtils.isEmpty(key)) return url var uri = Uri.parse(url) if (uri.isOpaque()) { return url } if (!url.contains("?")) { url + "?" } var urlStart = url.split("?").get(0) //利用Map的唯一性拼接参数 var parameterMap = getParameterMap(url) //利用map的唯一性 存储或者更新值 if (parameterMap.containsKey(key)){ parameterMap.remove(key) } //参数的map var appendUrl = appendMapParameter(parameterMap) var division = "?" return "$urlStart$division$appendUrl" } /** * 添加 Encode 的参数 */ fun addQueryParameterDecodeValue(url: String, key: String, value: String): String { if (TextUtils.isEmpty(url) || TextUtils.isEmpty(key)) return url var uri = Uri.parse(url) if (uri.isOpaque()) { return url } if (!url.contains("?")) { url + "?" } var urlStart = url.split("?").get(0) //利用Map的唯一性拼接参数 var parameterMap = getParameterMap(url) //利用map的唯一性 存储或者更新值 parameterMap.put(key, Uri.encode(value)) //参数的map var appendUrl = appendMapParameter(parameterMap) var division = "?" return "$urlStart$division$appendUrl" } /** * url 添加参数 */ fun addQueryParameterValue(url: String, key: String, value: String): String { if (TextUtils.isEmpty(url) || TextUtils.isEmpty(key)) return url var uri = Uri.parse(url) if (uri.isOpaque()) { return url } if (url.contains("#")) { url.replace("#", "%23") } if (!url.contains("?")) { url + "?" } var urlStart = url.split("?").get(0) //利用Map的唯一性拼接参数 var parameterMap = getParameterMap(url) //利用map的唯一性 存储或者更新值 parameterMap.put(key, value) //参数的map var appendUrl = appendMapParameter(parameterMap) var division = "?" return "$urlStart$division$appendUrl" } /** * map 拼接成字符串 */ private fun appendMapParameter(parameterMap: HashMap<String, String>): String { var stringBuilder = StringBuilder() parameterMap.keys.forEach { stringBuilder.append(it).append("=").append(parameterMap.get(it)).append("&") } if (stringBuilder.length > 0) { stringBuilder.deleteCharAt(stringBuilder.length - 1) } return stringBuilder.toString() } /** * 把url 的参数转为Map存储 */ private fun getParameterMap( url: String ): HashMap<String, String> { var map: HashMap<String, String> = HashMap<String, String>() // 参数名字的列表 var parameter = Uri.parse(url).queryParameterNames parameter.forEach { if (getQueryParameterDecodeValue(url, it) != null) map.put(it, getQueryParameterDecodeValue(url, it)!!) } return map }
2.获取重定向地址的真实地址
package com.wu.base.util; import android.text.TextUtils; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.concurrent.TimeUnit; import io.reactivex.Observable; import io.reactivex.ObservableOnSubscribe; import io.reactivex.ObservableSource; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** * @author wkq * @date 2022年07月22日 16:15 * @des 重定向Url处理工具 */ public class UrlRedirectUrlUtil { //是否Encode private static boolean isEncode = false; private static Disposable callDisposable; //获取重定向后的真实地址 public static String getRedirectUrl(String path) { boolean isEncode = false; if (TextUtils.isEmpty(path)) { return ""; } if (findEnd(path)) { return path; } if (isShortUrl(path)) return path; try { if (path.contains("#")) { path = path.replace("#", URLEncoder.encode("#")); isEncode = true; } OkHttpClient mOkHttpClient = new OkHttpClient(); Request request = new Request.Builder() .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8") .addHeader("Accept-Encoding", "gzip, deflate, br") .addHeader("Accept-Language", "zh-CN,zh;q=0.9") .addHeader("Connection", "keep-alive") .addHeader("User-Agent", "Mozilla/5.0 (Linux; Android 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Mobile Safari/537.36") .url(path) .build(); Call mCall = mOkHttpClient.newCall(request); Response response = mCall.execute(); String backUrl = response.header("Location"); if (response.code() != HttpURLConnection.HTTP_MOVED_TEMP && response.code() != HttpURLConnection.HTTP_MOVED_PERM) { String requestPath = response.request().url().toString(); if (isEncode) { requestPath = requestPath.replace("%23", URLDecoder.decode("%23")); isEncode = false; } return requestPath; } else { return getRedirectUrl(backUrl); } } catch (Exception e) { e.printStackTrace(); return path; } } //处理重定向的Url public static void getRedirectUrl(String url, ResponseCallBack callBack) { if (callBack == null) return; //取消上一个请求 cancelRequest(); if (TextUtils.isEmpty(url)) { callBack.getRedirectFail(); return; } if (findEnd(url)) { callBack.getRedirectSuccess(url); return; } if (isShortUrl(url)) { callBack.getRedirectSuccess(url); return; } callDisposable = Observable .create((ObservableOnSubscribe<String>) emitter -> { if (url.contains("#")) { isEncode = true; emitter.onNext(url.replace("#", URLEncoder.encode("#"))); } else { emitter.onNext(url); } emitter.onComplete(); }) .flatMap((Function<String, ObservableSource<String>>) s -> new Observable<String>() { @Override protected void subscribeActual(Observer<? super String> observer) { Request.Builder builder = new Request.Builder(); builder.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"); builder.header("Accept-Encoding", "gzip, deflate, br"); builder.header("Accept-Language", "zh-CN,zh;q=0.9"); builder.header("Connection", "keep-alive"); builder.header("User-Agent", "Mozilla/5.0 (Linux; Android 5.0; AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Mobile Safari/537.36"); Request request = builder.url(s).get().build(); OkHttpClient client = new OkHttpClient() .newBuilder() .followRedirects(false) .connectTimeout(10, TimeUnit.SECONDS)//设置连接超时时间 .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS)//设置读取超时时间 .build(); client.writeTimeoutMillis(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { observer.onError(new Throwable("解析失败")); } @Override public void onResponse(Call call, Response response) throws IOException { String path = url; if (response.code() == HttpURLConnection.HTTP_MOVED_TEMP || response.code() == HttpURLConnection.HTTP_MOVED_PERM) { String location = response.headers().get("Location"); if (!TextUtils.isEmpty(location)) { path = location; } if (isEncode) { path = path.replace("%23", URLDecoder.decode("%23")); isEncode = false; } } observer.onNext(path); observer.onComplete(); } }); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( path -> callBack.getRedirectSuccess(path), throwable -> callBack.getRedirectFail()); } // 取消请求 public static void cancelRequest() { if (callDisposable != null && !callDisposable.isDisposed()) { callDisposable.dispose(); } } /** * 判断是否是是讯云短连接 * * @param url * @return */ public static boolean isShortUrl(String url) { return false; } /** * 判断外部链接.MP4结尾 */ public static boolean findEnd(String url) { if (url.endsWith(".mp4")) { return true; } return false; } public interface ResponseCallBack { void getRedirectSuccess(String url); void getRedirectFail(); } }
3.处理地址过长问题

日常开发的时候有一些三方SDK对Url的长度做出了限制,再加上日常使用过程中Url贼长让需要对Url做操作的同事极度反感,这个时候就需要对很长的Url做处理,以下是个人对长连接做的处理

  • 缩短器:后台来个长变短的服务,其实也就是一个字符串变短的算法,移动端请求接口即可
  • 对Url的参数进行编码使参数变短
4.Url参数编码问题

Url在分享,浏览器打开的时候中文或者特殊字符会影响Url的使用,所以在给Url处理参数的时候,给参数做统一编码(Encode)显得特别重要.假如是复杂和长期维护的项目,建议项目架构的时候就处理掉这个问题,不然后期会疯(亲身经历).

总结

日常开发中,会遇到各种各样的Url,所以涉及到的Url处理也就各种各样,建议将Url做一个统一进出的工具 统一管理各种Url的操作.其中涉及到的Url参数转码问题要慎重,要提前和H5和IOS沟通好防止出现Url处理不同意问题.

AI大模型学习福利

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。


因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

四、AI大模型商业化落地方案

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量

http://www.jsqmd.com/news/144043/

相关文章:

  • AbMole丨重组干扰素γ:免疫应答与巨噬细胞极化的调控因子
  • MAME 0.116 Ryuko-NEHT Reloaded 游戏列表与ROM信息
  • 2025年靠谱的geo推广营销服务哪家可靠?新测评精选营销公司推荐 - mypinpai
  • 告别人工干预!Open-AutoGLM让大模型真正“自己动起来”
  • 企业ICT连通性冗余管理:交换设备的系统冗余标准规范
  • Delphi 窗体间通信的经典解决方案,掌握后可以应对80%的窗体数据传递需求
  • 2026年Deepseek知识库部署方案商企业知识库部署厂商全景测评:私有化落地路径与选型宝 - 品牌2026
  • 厦门狄耐克以脑机交互技术,重塑全民脑健康新范式 - 速递信息
  • Rhino修复破面模型:从导入到导出完整指南
  • 学长亲荐8个AI论文工具,专科生毕业论文格式规范必备!
  • 揭秘Open-AutoGLM高效用法:3步实现自动化大模型调优
  • 【智谱清言使用全攻略】:3步开启Open-AutoGLM沉思模式,90%的人都不知道的隐藏功能
  • 基于NPort5630的Modbus串口通讯优化方案
  • 十大排序算法详解:原理与多语言实现
  • 2025盛世笔特国际文化创意产业集团有限公司推荐:口碑如何、创新能力怎么样、性价比好不好深度测评 - 工业设备
  • 为什么你的Open-AutoGLM跑不起来?这6步部署逻辑缺一不可
  • 【AI大模型调优实战】:深度解析智谱清言沉思模式启动机制与配置陷阱
  • JSP+JavaScript实现验证码登录功能
  • 函数封装(可复用)
  • TypeScript的个人理解
  • Open-AutoGLM能在家用电脑部署吗:5步完成本地化部署实测指南
  • .NET中为UEditor添加图片删除功能
  • Excel实用技巧大全:从入门到精通
  • Revit模型导入3ds Max的完整操作指南
  • 2025年免费软著查询渠道汇总!可以查到6项软著申请信息! - 还在做实验的师兄
  • Excel随机数生成与分布应用详解
  • 如何用Open-AutoGLM实现多语言动态菜单?90%人都忽略的3个细节
  • 拆解UUD白羊座蓝牙音箱MX02:音质与设计的平衡
  • 国标GB28181算法算力平台EasyGBS如何运用流媒体技术提升安防监控效率?
  • OpenCV4.2使用viz模块显示3D图像