美文网首页
通过fileProvider接收外部App传递文件路径的一些坑

通过fileProvider接收外部App传递文件路径的一些坑

作者: kongzue | 来源:发表于2018-10-16 09:39 被阅读242次

    问题

    由于Google的作死,现如今线版本的Android系统阻止了应用之间通过intent传递路径的行为,而通过此方法传递过来的路径会非常奇怪,直接获取会以类似如下形式表现:

     content://com.example.app.provider/storage/emulated/0/xxx...
    

    如果将它丢到new File(path)里则会导致出错,那么如何解决这样的奇葩路径呢?

    按照以往的方法,我们要读取到需要打开的文件的方法为:

    Intent intent = getIntent();
    if (intent != null) {
        String action = intent.getAction();
        if (action != null) {
            if (intent.ACTION_VIEW.equals(action)) {
                String uriPath = intent.getDataString();    //获取要打开文件的路径
                if (!isNull(uriPath)) {
                    //执行打开操作...
                } else {
                    //显示错误提示
                }
            }else if (intent.ACTION_SEND.equals(action)) {
                Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
                if (uri != null) {
                    String file = uri.getPath();
                    if (!isNull(file)) {
                        //执行打开操作...
                    } else {
                       //显示错误提示
                    }
                } else {
                    //显示错误提示
                }
            }
        }
    }
    

    但是显然,fileProvider传递过来并非通常意义的路径,我们无法直接进行打开操作,那么此时正确的方法为首先我们需要在接收“打开”操作的Activity中接收到系统传递过来的Intent:

    Uri data = getIntent().getData();
    

    接下来直接通过ContentResolver获取读取流进行读取文件内容:

    if (data != null) {
        InputStream inputStream = null;
        try {
            inputStream = getContentResolver().openInputStream(data);
            String content = readStreamToString(inputStream);
            //content 就是读取到的内容了,请直接食用
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ignored) {
                }
            }
        }
    }
    

    此时通过ContentResolver获取到读取流就可以轻松读取到外部App传递过来的文档内容了。文中的content即读取到的文件所有内容,当然了,如果是图片也可以通过inputStream读取到,请按具体情况进行修改。

    但是注意,如果遇到低版本的App,依然会传递以前方式正确路径过来,此时通过fileProvider法又无法读取内容,那么在这里我们就要做到新旧兼容,请参阅下述的完整代码:

    完整代码

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        //尝试使用fileProvider方式读取
        Uri data = getIntent().getData();
        if (data != null) {
            InputStream inputStream = null;
            try {
                inputStream = getContentResolver().openInputStream(data);
                String content = readStreamToString(inputStream);
                
                //请对读取到的内容content进行处理...
    
            } catch (Exception e) {
                //如果不支持,尝试老方法
                doTryOldReader(getIntent());
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException ignored) {
                    }
                }
            }
        }else{
            //如果不支持,尝试老方法
            doTryOldReader(getIntent());
        }
    }
    
    //部分旧文件浏览器可以直接将路径发过来的情况执行下边的方法
    private void doTryOldReader(Intent intent) {
        if (intent != null) {
            String action = intent.getAction();
            if (action != null) {
                if (intent.ACTION_VIEW.equals(action)) {
                    String uriPath = intent.getDataString();
                    
                    if (!isNull(uriPath)) {
                        //在此处读取uriPath路径的文件即可
                    } else {
                        //错误提示
                    }
                }
                if (intent.ACTION_SEND.equals(action)) {
                    Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
                    if (uri != null) {
                        String file = uri.getPath();
                        
                        if (!isNull(file)) {
                            //在此处读取uriPath路径的文件即可
                        } else {
                            //错误提示
                        }
                    } else {
                        //错误提示
                    }
                }
            } else {
                //错误提示
            }
        } else {
            //错误提示
        }
        finish();
    }
    

    完。

    相关文章

      网友评论

          本文标题:通过fileProvider接收外部App传递文件路径的一些坑

          本文链接:https://www.haomeiwen.com/subject/qyyczftx.html