ionic项目中调用本地应用打开请求的网络word、pdf、txt等文件

文章目录

          • 一、实现思路
          • 二、动手实践
            • 1. 编写自定义的插件:
          • 三、怎么调用
            • 1.在ionic项目中需要配合File、FileTransfer进行使用。既然需要组合,那我们写一个工具service。
            • 2. 业务调用
          • 四、问题解决
            • 1. 真机下:android.os.FileUriExposedException:exposed beyond app through Intent.getData()
            • 2. 编译报错:Didn't find class "android.support.v4.content.FileProvider" on path:
          • 五、参考资源

一、实现思路

我们在写插件之前需要想清楚:
1. 网络资源只是一个请求链接不是真正的文件
2. 调用本地应用打开文件,这个文件是不是需要真实存在本地,才能打开。
3. 如果需要存在本地目录,那么应该存在什么样的目录。
想清楚之后我们来实现:
首先我来说下我的实现思路:
点击请求链接 —> 获取请求链接 —> 根据链接下载网络资源到本地 —> 调用自定义插件 —> 调用本地应用打开下载到本地的资源文件

二、动手实践
1. 编写自定义的插件:

1.使用plugman创建自己的自定义插件,并添加android平台
2.编辑调用的openFile.js

var exec = require('cordova/exec');
exports.openFile = function (param, success, error) {
    exec(success, error, 'OpenFilePlugin', 'openFile', [param]);
};

3.编辑实现的功能的java类

package com.ai.ced.openfile;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.FileProvider;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;

import org.json.JSONArray;
import org.json.JSONException;

import java.io.File;

/**
 * This class echoes a string called from JavaScript.
 */
public class OpenFilePlugin extends CordovaPlugin {

    public static Activity activity;

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("openFile")) {
            String message = args.getString(0);
            this.openFile(message, callbackContext);
            return true;
        }
        return false;
    }

    private void openFile(String message, CallbackContext callbackContext) {
        this.activity = this.cordova.getActivity();
//        this.openAndroidFile("/storage/emulated/0/ReleaseChannel.txt");

        this.openAndroidFile(message);
    }

    public  void openAndroidFile(String filepath){
        Intent intent = new Intent();
        File file = new File(filepath);
//        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//设置标记
        Uri uri = FileProvider.getUriForFile(activity,
        BuildConfig.APPLICATION_ID + ".fileProvider",
        file);

        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setAction(Intent.ACTION_VIEW);//动作,查看
//        intent.setDataAndType(Uri.fromFile(file), this.getMIMEType(file));//设置类型
        intent.setDataAndType(uri, this.getMIMEType(file));//设置类型
        this.activity.startActivity(intent);
    }


    private String getMIMEType(File file) {

        String type="*/*";
        String fName = file.getName();
        //获取后缀名前的分隔符"."在fName中的位置。
        int dotIndex = fName.lastIndexOf(".");
        if(dotIndex < 0)
            return type;
        /* 获取文件的后缀名 */
        String fileType = fName.substring(dotIndex,fName.length()).toLowerCase();
        if(fileType == null || "".equals(fileType))
            return type;
        //在MIME和文件类型的匹配表中找到对应的MIME类型。
        for(int i=0;i

到这主要的功能就已经完成了。

三、怎么调用
1.在ionic项目中需要配合File、FileTransfer进行使用。既然需要组合,那我们写一个工具service。
import { Injectable } from '@angular/core';
import { FileTransferObject, FileTransfer } from '@ionic-native/file-transfer';
import { File } from '@ionic-native/file';
import { CommonUtilService } from './commonUtilService';

declare let OpenFilePlugin: any;

/*
  Generated class for the WechatShareServiceProvider provider.

  See https://angular.io/guide/dependency-injection for more info on providers
  and Angular DI.
*/

@Injectable()
export class OpenFileService {

  constructor(private transfer: FileTransfer,
              private comUtil: CommonUtilService,
              private file: File) {}


  openFile(url: string){
    console.log("OpenFileService enter");
    const fileTransfer: FileTransferObject = this.transfer.create();
    // const url = 'http://www.gz10010.shop/resource/download/1111111111111111111111.pdf';
    // 获取文件名1111111111111111111111.pdf
    let tempUrl = url.substr(url.lastIndexOf("/")+1);
    // 获取存储路径
    // this.file.externalCacheDirectory获取对应app的缓存路径file:///storage/emulated/0/Android/data/io.ionic.starter/cache/
    // 需要去掉 file:/// 如果不去掉会报路径找不到该路径
    // /storage/emulated/0/Android/data/io.ionic.starter/cache/ 正确路径
    let storeUrl = this.file.externalCacheDirectory.substr(7);
    fileTransfer.download(url, storeUrl + tempUrl).then( (data) => {
      // 拼接打开的文件路径
      let openUrl = storeUrl + tempUrl;
      OpenFilePlugin.openFile(openUrl);
    }).catch( err => {
      this.comUtil.showAlert({title: "文件下载失败", message: JSON.stringify(err)});
    });
  }
}
2. 业务调用

在这里插入图片描述
ionic项目中调用本地应用打开请求的网络word、pdf、txt等文件_第1张图片

四、问题解决
1. 真机下:android.os.FileUriExposedException:exposed beyond app through Intent.getData()

方案一:
1.在AndroidManifest.xml文件的application里添加



              




2.在res目录下新建一个xml文件夹,并且新建一个file_paths的xml文件
3.打开file_paths.xml文件添加如下内容



             
             

方案二:
在MainActivity的onCreate方法中添加如下代码

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());
        }
2. 编译报错:Didn’t find class “android.support.v4.content.FileProvider” on path:

添加v4依赖包,重新clean、rebuild
ionic项目中调用本地应用打开请求的网络word、pdf、txt等文件_第2张图片

五、参考资源

FileProvider:
https://blog.csdn.net/u010773839/article/details/72886332
https://blog.csdn.net/fox_wei_hlz/article/details/78732907
https://www.cnblogs.com/netcorner/p/6542373.html
https://blog.csdn.net/z_x_Qiang/article/details/79940700
https://blog.csdn.net/acesheep_911/article/details/81708254
https://blog.csdn.net/biickvtkd/article/details/78803481
插件代码:
https://blog.csdn.net/u012527802/article/details/48464803
https://blog.csdn.net/luoyayun361/article/details/82746576

你可能感兴趣的:(ionic)