前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Android][Framework]记一个Uri相关的奇葩bug

[Android][Framework]记一个Uri相关的奇葩bug

作者头像
wOw
发布2020-01-20 16:55:13
1.3K0
发布2020-01-20 16:55:13
举报
文章被收录于专栏:wOw的Android小站wOw的Android小站

安装爱奇艺之后,搜索一个外链视频,然后点击播放,就会出现crash。

这个Bug只在我们的系统里出现,在手机上安装不存在这个现象。

那就很奇怪了,我们的系统又做了什么错事?作为负责系统的,我慌的一逼,赶紧抓一份log分析。

crash log:

代码语言:javascript
复制
--------- beginning of crash
01-04 15:54:29.614  3743  3743 E AndroidRuntime: FATAL EXCEPTION: main
01-04 15:54:29.614  3743  3743 E AndroidRuntime: Process: com.qiyi.video.pad, PID: 3743
01-04 15:54:29.614  3743  3743 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.qiyi.video.pad/org.qiyi.android.video.activitys.CommonWebViewNewActivity}: java.lang.UnsupportedOperationException: This isn't a hierarchical URI.
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.ActivityThread.-wrap12(ActivityThread.java)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:102)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:154)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:6119)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:900)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:790)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: Caused by: java.lang.UnsupportedOperationException: This isn't a hierarchical URI.
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.net.Uri.getQueryParameter(Uri.java:1685)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at com.qiyi.h.com1.aX(Unknown Source)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at org.qiyi.android.video.activitys.CommonWebViewNewActivity.aCW(Unknown Source)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at org.qiyi.android.video.activitys.CommonWebViewNewActivity.aiS(Unknown Source)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at org.qiyi.android.video.activitys.CommonWebViewNewActivity.v(Unknown Source)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at org.qiyi.android.video.activitys.CommonWebViewBaseActivity.onCreate(Unknown Source)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:6720)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
01-04 15:54:29.614  3743  3743 E AndroidRuntime: 	... 9 more
01-04 15:54:29.621  1228  2156 W ActivityManager:   Force finishing activity com.qiyi.video.pad/org.qiyi.android.video.activitys.CommonWebViewNewActivity

根据

代码语言:javascript
复制
UnsupportedOperationException: This isn't a hierarchical URI.

所以简单跟踪一下Uri代码:

报错的地方在:

代码语言:javascript
复制
/**
 * Returns a set of the unique names of all query parameters. Iterating
 * over the set will return the names in order of their first occurrence.
 *
 * @throws UnsupportedOperationException if this isn't a hierarchical URI
 *
 * @return a set of decoded names
 */
public Set<String> getQueryParameterNames() {
    if (isOpaque()) {
        throw new UnsupportedOperationException(NOT_HIERARCHICAL);
    }

这里就是抛出this isn't a hierarchical URI异常的地方,所以查看isOpaque什么情况下返回true

代码语言:javascript
复制
/**
 * Returns true if this URI is opaque like "mailto:nobody@google.com". The
 * scheme-specific part of an opaque URI cannot start with a '/'.
 */
public boolean isOpaque() {
    return !isHierarchical();
}

额,也就是说要调查isHierarchical在什么时候返回false

代码语言:javascript
复制
/**
 * Returns true if this URI is hierarchical like "http://google.com".
 * Absolute URIs are hierarchical if the scheme-specific part starts with
 * a '/'. Relative URIs are always hierarchical.
 */
public abstract boolean isHierarchical();

emmmm,它是个抽象方法,那就看一下他的实现。因为实在Uri.java定义的,查找继承Uri的类们,看其实现方法。从代码里搜到所有的继承都在Uri.java的内部类,所以直接搜,最后定位到是在StringUri里面实现的isHierarchical()方法处理后返回的false

代码语言:javascript
复制
public boolean isHierarchical() {
    int ssi = findSchemeSeparator();

    if (ssi == NOT_FOUND) {
        // All relative URIs are hierarchical.
        return true;
    }

    if (uriString.length() == ssi + 1) {
        // No ssp.
        return false;
    }

    // If the ssp starts with a '/', this is hierarchical.
    return uriString.charAt(ssi + 1) == '/';
}

/** Finds the first ':'. Returns -1 if none found. */
private int findSchemeSeparator() {
    return cachedSsi == NOT_CALCULATED
        ? cachedSsi = uriString.indexOf(':')
        : cachedSsi;
}

这个方法逻辑是:

  • 先从uriString里面查找:并记录其位置
  • 如果没找到,直接返回true,相当于不做处理
  • 再判断uriString的长度是否到:为止,如果是返回false
  • 最后判断:后面的字符是否是/

所以知道最后处理的uriString是什么就很关键了,通过添加log,编译系统,找到最后出问题的uriString是:

代码语言:javascript
复制
uristring is deviceId=22b0e7ce4a35edca010和谐&platform=GPad&network=1&ov=7.1.1:1.和谐&location=121.372360,31.176649

行吧。我就用你爱奇艺播放个视频而已,你看看你干了些什么?又读我设备ID,又读当前位置,还给我搞出来一个Bug。我TM一刀…算了40米的长刀拔出来太麻烦,还是看问题吧。

这个Uri本来应该在第一处判断就返回true的,但是因为版本号有一个7.1.1:1.xxxx,结果匹配上了冒号,最终因为:后面没有/返回一个false状态。

好嘛,半天是因为我们定义release版本号导致的这个问题。

最后也算长了点经验,以后在Android里字串连接的时候尽量不要用:了,否则不知道什么时候在哪里会挖出来一个坑。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档