最近公司提了个需求,实现手机上点击附件名称可以直接打开预览的功能。可以提供几个思路:

1.利用poi组件把附件转换成html然后再打开,实现比较麻烦。(没有实现,因为服务器端不是我们写的,我们是调用别人的接口)

2.谷歌提供了一个url接口,可以直接实现附件预览,方法“https://docs.google.com/viewer?url=文件具体的路径”。可惜此方法行不通,中国人都明白。

3.其实国内也提供了类似谷歌的预览方式,我找到的有 web office 365。可是这个免费服务内容比较少,要实现客户的需求就咬花钱啦!所以,排除了。

4.先下载,再用第三方软件打开(这里我用的是wps)。

此项目中我用的方法就是第4种,经济实惠又不烦琐。好了闲话少说直接进入主题。

首先下载文件 :

    /*** 打开附件* @param view*/public void openFile(View view) {NetworkHelper.doGet("http://112.27.197.248:9909/ctop/Documents/1500511784978.doc",null,new HttpCallbackListener() {@Overridepublic void onSuccess(byte[] response) {Log.e(TAG, response + "");write(response);}@Overridepublic void onError(Exception e) {Log.e(TAG, e.getMessage());e.printStackTrace();}});}

这里需要往手机中写文件,所以用到了android的存储权限,在android6.0之后需要用到动态申请权限,代码如下:

    /*** 写文件的权限申请* @param content*/private void write(byte[] content) {this.content = content;if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);}else{write2SD(content);}}/*** 权限申请* @param requestCode* @param permissions* @param grantResults*/@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if (requestCode == MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE){if (grantResults[0] == PackageManager.PERMISSION_GRANTED){write2SD(content);} else{// Permission DeniedToast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();}return;}super.onRequestPermissionsResult(requestCode, permissions, grantResults);}/*** 写文件* @param content*/private void write2SD(byte[] content) {FileUtil fileUtil = new FileUtil(this);File file = fileUtil.write2SDFromByte("doc/", "1500511784978.doc", content);open(file.getAbsolutePath());Log.i(TAG, "文件保存到:" + file.getAbsolutePath());}

附件打开:

    /*** 用第三方软件打开附件* @param path*/private void open(String path) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addCategory(Intent.CATEGORY_DEFAULT);File file = new File(path);Uri uri = Uri.fromFile(file);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.setDataAndType(uri, "application/msword");startActivity(intent);}

本人的测试手机是小米2s,android5.0(哎,穷屌丝一枚),测试没有问题,然后再拿同事手机(android6.0)测试也可以。

打包提交。本来以为功能完成了,可是现实很残酷,第二天用户反馈,华为荣耀、小米6点击闪退,什么鬼,闪退?跟客户一聊解

情况原来出问题的都是android7.0手机。通过一番搜索发现android7.0不允许以"file:///"(Uri.fromFile(file);)的形式共享文件,要使用

content://URI的格式,并授予URI临时访问权限才行。android也提供了解决方案:FileProvider。

FileProvider的使用:

首先要在清单文件(manifest)中添加

<manifest>...<application>...<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="${applicationId}.provider"android:exported="false"android:grantUriPermissions="true"><meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /></provider> ... </application></manifest>

//exported:要求必须为false,为true则会报安全异常。

//grantUriPermissions:true,表示授予 URI 临时访问权限。

然后,再在res/xml下添加provider_paths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><external-path name="external_files" path="."/><external-files-path name="external_files" path="." />
</paths>

其中
<external-path /> 代表目录:Environment.getExternalStorageDirectory()
<external-files-path /> 代表目录:ContextCompat.getExternalFilesDirs(context, null)[0](ContextCompat.getExternalFilesDirs(context, null)返回一个File[])
<cache-path/>代表的根目录: getCacheDir()
<files-path />代表的根目录:context.getFilesDir()
<external-cache-path />代表的根目录:ContextCompat.getExternalCacheDirs(context)[0](ContextCompat.getExternalCacheDirs(context)返回一个File[])
<root-path />代表的目录: "/",根目录

最后,分享文件可修改为:

    /*** 用第三方软件打开附件* @param path*/private void open(String path) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addCategory(Intent.CATEGORY_DEFAULT);setFlags(intent);Uri uri = getUri(path);intent.setDataAndType(uri, "application/msword");startActivity(intent);}/*** 适配android7.0的文件打开* @param intent*/private void setFlags(Intent intent) {if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);} else {intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}}public Uri getUri(String UrlStr) {File file = new File(UrlStr);Uri uri;//判读版本是否在7.0以上if (Build.VERSION.SDK_INT >= 24) {//provider authoritiesuri = FileProvider.getUriForFile(this, getPackageName()+".provider", file);} else {uri = Uri.fromFile(file);}return uri;}

。。。。。。。。
你以为这样就完了?大错特错,这种方案在没有sd卡的机型上完全没有问题,但是要是带有sd卡的机型那就蛋疼了(要把存储设置成sd卡存储才能测试出问题)。首先他会给你一个异常 "Failed to find configured root that contains " + filePath,怎么样找不着北了吧。赶紧找资料发现原来有个标签<root-path />(还纳闷这个标签用来干嘛的),除了这个其他的标签全部不能适用于sd卡上,坑爹啊!然后赶紧在provider_paths.xml中加上<root-path name="linyeting" path="." />测试可以了。注意文件下载保存的路径一定要跟标签设置的保持一致,不然会出现只打开wps而没有内容的情况。出现这种情况的原因应该是标签转换的content://URI路径和文件保存的路径不一样,导致找不到文件(这个坑我花了三天的时间才发现抓狂)。但是我在没有把sd卡设置成默认存储的时候,文件保存路径是:Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),provider_paths.xml中配置的是<external-path name="external_files" path="."/>(这个对应路径是Environment.getExternalStorageDirectory())。可见两个路径不一致,但是文件照样能打开。我也是懵逼了,不知道是啥原因,如有大神知道还望指点一二。。

Demo下载。

Android实现附件预览相关推荐

  1. android打开预览文件格式,Android中文档预览功能的实现思路及问题

    Andriod中的文档在线查看功能,类似于网易邮箱大师中的附件预览功能,要求在app内直接打开office文档.pdf文档等. 思路一:后台统一转换文档格式,安卓端只预览一种格式文档. 在后台将off ...

  2. Android Wear开发者预览版入门

    Android Wear开发者预览版包括工具和API,增强了应用程序通知功能,提供针对Android可穿戴设备的最佳用户体验. 利用Android Wear开发者预览,你可以: 在Android模拟器 ...

  3. 关于surface安装foxmail附件预览失效解决方案

    surface安装foxmail附件预览失效/没反应 说在前面的:为了支持与体验微软,买了一台surface,确实刷新了对笔记本电脑的认知,轻薄,触屏.键盘磁吸这才是正儿八经的的体验win10,同时已 ...

  4. android应用窗口模式,[技巧]如何启用Android N开发者预览版中的“自由窗口”模式...

    这里是Android N开发者预览版"自有窗口"模式的一些实际演示截图. 对于已经参加了"Beta Program"的人们来说,通过OTA获取Android N ...

  5. Android P 开发者预览版

    Android P 开发者预览版首发! 在上周的世界移动通信大会 (Mobile World Congress) 上,我们看到由开发者.设备厂商以及芯片合作伙伴组成的 Android 生态系统不断为全 ...

  6. android p preview_细数 Android P 开发者预览版中最不能错过的新特性

    原标题:细数 Android P 开发者预览版中最不能错过的新特性 2018年安卓巴士全球开发者论坛-重庆站 [线下活动]春天到了 跟小编一起去重庆嗨皮吧~ Android P 应用适配新特性1.Pr ...

  7. 罗永浩宣布进军电商直播;微博回应用户数据泄露;Android 11 开发者预览版 2 发布 | 极客头条...

    整理 | 屠敏 头图 | CSDN 下载自视觉中国 快来收听极客头条音频版吧,智能播报由标贝科技提供技术支持. 「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦, ...

  8. 神经网络API、Kotlin支持,那些你必须了解的Android 8.1预览版和Android Studio 3.0新特性

    曾仅用 55 秒发布会的 Android 8.0 Oreo 在时隔两个月后,Google 于今天在其官方网站上正式发布了 Android 8.1 首个开发者预览版,此次升级涵盖了针对多个功能的提升优化 ...

  9. Android N开发者预览版(第二版)发布

    上个月,我们发布了首个Android N的开发者预览版,本文将带你先睹为快,一窥新发布的Android N开发者预览版第二版.大家的反馈帮助我们找出了很多bug,再对功能做出改进并修复一些bug后,我 ...

最新文章

  1. 普华永道:人工智能将重塑职位格局并与物联网合并
  2. linux内核线程创建销毁机制
  3. 硬件工程师面试经历2015---笔试篇
  4. 我的ubunt开发环境 (操作备份)
  5. PyCharm远程链接矩池云
  6. 需要友元的原因及使用
  7. 机器学习代码实战——拆分训练集与测试集(train_test_split)
  8. 一个RSS阅读器的开源 ---- 邀请您加入开发队伍
  9. 软考中级网络工程师备考详细资料
  10. axure rp编辑html模板,AxureRP教程—用模板封装UI标准
  11. Activiti6.0 - 核心数据库表及字段注释说明
  12. FileZilla Server1.5使用入门
  13. 宏观经济学 马工程教材个人笔记整理
  14. 串口通信协议c语言程序,串口通信协议源代码.doc
  15. 这四本第四届橙瓜网络文学奖体育竞技分类前五的作品不能不看!
  16. 手机中的计算摄影-超广角畸变校正
  17. 科技热点周刊|GitLab 上市、LinkedIn 中国停止运营、Visual Studio 2022 正式版将发布
  18. android仿支付宝弹窗,实现支付宝支付从底部弹窗效果
  19. 计算机盖,盖珂珂_北京理工大学计算机学院
  20. JS逆向 2021-8-16 网易云音乐 params、encSecKey参数

热门文章

  1. cmd进入指定盘文件夹
  2. Warning C4996的说明与关闭
  3. 2013第四届蓝桥杯JavaA组省赛真题详解
  4. 5种电商数据的采集工具
  5. aps.net导出数据库信息到excel后下载
  6. Css 结构伪类选择器
  7. 离线计算系统综合案例
  8. svg的简介-svg转png的坑
  9. 7-12 电话聊天狂人
  10. rsem比对_无参转录组分析:使用 Trinity 进行转录本拼接(参考脚本)