安卓:pathPattern为单个文件文件、pathPattern

由网友(斷情音)分享简介:我需要定义的IntentFilter 名为单个文件 myfile.ext 。此刻我的清单如下:I need to define IntentFilter for single file named myfile.ext. At the moment my manifest looks like:我需要定义的IntentFilter 名为单个文件 myfile.ext 。此刻我的清单如下:

I need to define IntentFilter for single file named myfile.ext. At the moment my manifest looks like:

        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <action android:name="android.intent.action.EDIT" />
            <category android:name="android.intent.category.DEFAULT" />
            <data
                android:scheme="file"
                android:mimeType="*/*"
                android:host="*"
                android:pathPattern=".*myfile.ext"
            />
        </intent-filter>

我也尝试过其他的变种,如:的android:pathPattern =* \ myfile.ext。等等 - 但它仍然不处理我的文件

I have also tried other variants like: android:pathPattern=".*myfile.ext" and so on - but still it doesn't handle my file.

任何线索?

推荐答案

Android的模式细节:

匹配任意字符。 * 0匹配或多次出现的字符$ P $的pceding它。 。* 0匹配或多次出现的任意字符。 用于图案逃避特殊字符。 当字符串从XML文件中读取也用作转义字符。因此,在模式中,双斜线 \ 逃避特殊字符已被使用。 . matches any character. * matches 0 or more occurrences of the character preceding it. .* matches 0 or more occurrences of any character. is used to escape special characters in pattern. is also used as an escape character when the string is read from the XML file. Hence to escape special character in a pattern, double-slash has to be used.

问题:在这种模式中。* \ \ MYFILE分机,您试图转义字符 M 这是一个正常的字符。因此,它并没有任何区别。它等同于。* MYFILE \分机。意图的数据URI的部分是文件:///mnt/sdcard/tmp/myfile.ext 。该模式是/mnt/sdcard/tmp/myfile.ext 对匹配,但它失败。

Issue: In this pattern ".*myfile.ext", you are trying to escape character m which is a normal character. Hence it does not make any difference. It is equivalent to ".*myfile.ext". The data uri part of intent is file:///mnt/sdcard/tmp/myfile.ext. The pattern is matched against /mnt/sdcard/tmp/myfile.ext, but it fails.

。* 尝试任意字符匹配,直到 M 中第一次出现,这恰好是第二个字符即的/ mnt 。 模式预计,下一个字符是,但它得到 N ,因此该模式匹配失败。

.* tries to match any character until the first occurrence of m, which happens to be the 2nd char i.e. /mnt. Pattern expects the next char to be y, but it gets n and hence the pattern match fails.

解决方案:对于上面的路径,模式 /.*/.*/.*/ MYFILE \分机

有关 /mnt/sdcard/myfile.ext 路径,模式 /.*/.*/ MYFILE \分机的作品。如果你不能确定子目录级别,你将不得不添加多个&lt;数据&GT; 用不同的元素 pathPattern 值。

For /mnt/sdcard/myfile.ext path, pattern /.*/.*/myfile.ext works. If you are not sure the sub-directory level, you will have to add multiple <data> element with different pathPattern values.

<data
    android:scheme="file"
    android:mimeType="*/*"
    android:host="*" />

<data android:pathPattern="/.*/.*/.*/myfile.ext" /> <!-- matches file:///mnt/sdcard/tmp/myfile.ext -->

<data android:pathPattern="/.*/.*/myfile.ext" /> <!-- matches file:///mnt/sdcard/myfile.ext -->

下面是 PatternMatcher.matchPattern 方式:

   static boolean matchPattern(String pattern, String match, int type) {
        if (match == null) return false;
        if (type == PATTERN_LITERAL) {
            return pattern.equals(match);
        } if (type == PATTERN_PREFIX) {
            return match.startsWith(pattern);
        } else if (type != PATTERN_SIMPLE_GLOB) {
            return false;
        }

        final int NP = pattern.length();
        if (NP <= 0) {
            return match.length() <= 0;
        }
        final int NM = match.length();
        int ip = 0, im = 0;
        char nextChar = pattern.charAt(0);
        while ((ip<NP) && (im<NM)) {
            char c = nextChar;
            ip++;
            nextChar = ip < NP ? pattern.charAt(ip) : 0;
            final boolean escaped = (c == '');
            if (escaped) {
                c = nextChar;
                ip++;
                nextChar = ip < NP ? pattern.charAt(ip) : 0;
            }
            if (nextChar == '*') {
                if (!escaped && c == '.') {
                    if (ip >= (NP-1)) {
                        // at the end with a pattern match, so
                        // all is good without checking!
                        return true;
                   }
                    ip++;
                    nextChar = pattern.charAt(ip);
                    // Consume everything until the next character in the
                    // pattern is found.
                    if (nextChar == '') {
                        ip++;
                        nextChar = ip < NP ? pattern.charAt(ip) : 0;
                    }
                    do {
                        if (match.charAt(im) == nextChar) {
                            break;
                        }
                        im++;
                    } while (im < NM);
                    if (im == NM) {
                        // Whoops, the next character in the pattern didn't
                        // exist in the match.
                        return false;
                    }
                    ip++;
                    nextChar = ip < NP ? pattern.charAt(ip) : 0;
                    im++;
                } else {
                    // Consume only characters matching the one before '*'.
                    do {
                        if (match.charAt(im) != c) {
                            break;
                        }
                        im++;
                    } while (im < NM);
                    ip++;
                    nextChar = ip < NP ? pattern.charAt(ip) : 0;
                }
            } else {
                if (c != '.' && match.charAt(im) != c) return false;
                im++;
            }
        }

        if (ip >= NP && im >= NM) {
            // Reached the end of both strings, all is good!
            return true;
        }

        // One last check: we may have finished the match string, but still
        // have a '.*' at the end of the pattern, which should still count
        // as a match.
        if (ip == NP-2 && pattern.charAt(ip) == '.'
            && pattern.charAt(ip+1) == '*') {
            return true;
        }

        return false;
    }