通过fileProvider接收外部App传递文件路径的一些坑
2018-10-16 本文已影响242人
kongzue
问题
由于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();
}
完。