1. 打包后手机安装无法发送请求
- 可尝试修改platforms\android\app\src\main\AndroidManifest.xml
//android升级之后 默认不允许使用明码协议,需要补充android:usesCleartextTraffic="true"
<application android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
android:supportsRtl="true"
android:usesCleartextTraffic="true">
</application>
2. Cordova自定义插件
- 使用plugman生成插件
- plugman安装:npm install –g plugman
- 创建插件:
- plugmanName : 插件名字
- pluginID : 插件ID
- version : 0.0.1
- directory : 一个绝对或相对路径的目录,该目录将创建插件项目
- variableNAME=VALUE: 额外的描述,如作者信息和相关描述
//命令
plugman create –name<plugmanName> --plugin_id<pluginID> --plugin_version<version>
[--path<directory>][--variableNAME=value]
//示例
plugman create --name ToastPlugin --plugin_id com.example.toast --plugin_version 1.0.0
- 插件初始化:npm init
- 插件添加平台
- plugman platform add –platform_name android
- plugman platform add –platform_name ios
- 配置plugin.xml
<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-toastdemo" version="1.0.0"
xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<name>ToastDemo</name>
<!-- js调用模块:src为调用插件的js文件路劲 -->
<js-module name="ToastDemo" src="www/ToastDemo.js">
<!-- target为插件安装后的调用方法前缀,如cordova.plugins.ToastDemo.[插件方法名] -->
<!-- <clobbers target="cordova.plugins.ToastDemo" /> -->
<!-- 可以自定义,调用时:ToastDemo.[插件方法名] -->
<clobbers target="ToastDemo"/>
</js-module>
<!-- android环境配置项 -->
<platform name="android">
<!-- 插件配置,target为插件安装时,Cordova项目Android环境配置文件的位置 -->
<!-- 插件安装时将config-fileb标签中的内容添加到res/xml/config.xml文件中 -->
<config-file parent="/*" target="res/xml/config.xml">
<!-- name对应ToastDemo.js中exec方法的第三个参数 -->
<feature name="ToastDemo">
<!-- value为插件安装到项目中后ToastDemo.java文件的路径,即包路径 -->
<param name="android-package" value="cordova.plugin.toastdemo.ToastDemo" />
</feature>
</config-file>
<!-- 这里添加权限 四大组件等信息,这里此节点下的内容会被复制到Android项目中的AndroidManifest清单文件中 -->
<config-file parent="/*" target="AndroidManifest.xml">
</config-file>
<!-- src为插件中需要拷贝的文件的插件中的路径-->
<!-- target-dir为插件安装到Android平台后对应的包文件夹路径,省略了android -->
<source-file src="src/android/com/cordova/plugin/toastdemo/ToastDemo.java" target-dir="src/cordova/plugin/toastdemo/" />
<!-- jar包文件夹路径 -->
<source-file src="src/android/myself.jar" target-dir="libs"/>
</platform>
</plugin>
- 配置ToastDemo.js
var exec = require('cordova/exec');
//exports.toast的toast为js中调用的方法名,其中传递的参数可以任意多个 如:(arg0,arg1,arg2...,success,error)
exports.toast = function (arg0, success, error) {
// arg1:成功回调js函数
// arg2:失败回调js函数
// arg3:与plugin.xml中feature节点的name属性值相同
// arg4:java代码中用于判断调用方法的action参数
// arg5:参数,json格式
exec(success, error, 'ToastDemo', 'toast', [arg0]);
};
- 撰写实现类ToastDemo.java
package cordova.plugin.toastdemo;
import android.widget.Toast;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class ToastDemo extends CordovaPlugin {
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
//判断action调用不同的实现方法
if (action.equals("toast")) {
String message = args.getString(0);
//调用对应方法
this.showToast(message, callbackContext);
return true;
}
return false;
}
//弹出Toast的方法
private void showToast(String message, CallbackContext callbackContext) {
if (message != null && message.length() > 0) {
Toast.makeText(cordova.getContext(), message, Toast.LENGTH_SHORT).show();
callbackContext.success(message);
} else {
callbackContext.error("Expected one non-empty string argument.");
}
}
}
- Cordova项目引入插件:Cordova plugin add E:\ToastDemo
几个要点:
- 插件实现类继承于CordovaPlugin(所有自定义插件,都要继承CordovaPlugin),最后重写execute方法。
- execute有三个重载方法:最后都调用了第二个方法
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext)
- public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext)
- public boolean execute(String action, String rawArgs, CallbackContext callbackContext)
- excute方法的参数
- String action:一个类里面可以提供多个功能,action就是指名了要调用哪个功能。
- CordovaArgs args:web以json的数据格式传递给Android native,CordovaArgs 是对JSONArray 的一个封装。
- CallbackContext callbackContext:这个是回调给web,有success和error两种回调方法。
- cordova默认是调用一次callbackContext.error或者success就会不再对上端JS继续传输数据
- 在使用第三方插件时,如果自行扩展了插件,在用命令行工具编译时要使用 cordova compile 而不要用 cordova build 命令。
- cordova build 命令是 cordova prepare + cordova compile,而 cordova prepare 命令做的就是根据插件中的 config.xml 将插件文件复制到项目中,这样就会把你修改了的插件文件替换掉,所以如果只是想编译项目,就只使用 cordova compile 命令
3. exposed beyond app through Intent.getData()
- 报错原因:
- Android 7.0之前通过文件的地址获取的File对象new File("URL地址")可以正常打开文件
- Android 7.0之后出于用户隐私安全考虑,对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在应用外部公开 file://URI。
- 推荐方法是使用 FileProvider
4. fileopener插件引入FileProvider
- 单独写了个FileProvider.java,也可以直接调用android.support.v4.content.FileProvider
package fr.smile.cordova.fileopener;
public class FileProvider extends android.support.v4.content.FileProvider {
}
- 实现打开逻辑里调用FileProvider获取uri
File tempFile= new File(fileURL);
Uri uri ;
//Android sdk24一下可以不用转换
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
uri = Uri.fromFile(tempFile);
} else {
//参数2需要与AndroidManifest.xml里provider标签的android:authorities对应
uri = FileProvider.getUriForFile(context,
cordova.getActivity().getPackageName() + ".fileOpener2.provider", tempFile);
}
- 修改后的plugin.xml
<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-fileopener" version="1.0.5" xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<name>FileOpener</name>
<description>Plugin to download and open files with default application for Android devices</description>
<author>Samuel Martineau</author>
<license>MIT</license>
<keywords>file, downloader, opener, android, extension, MIME types, cordova, plugin</keywords>
<repo>https://github.com/Smile-SA/cordova-plugin-fileopener</repo>
<js-module name="FileOpener" src="www/FileOpener.js">
<clobbers target="cordova.plugins.FileOpener"/>
</js-module>
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="FileOpener">
<param name="android-package" value="fr.smile.cordova.fileopener.FileOpener"/>
</feature>
</config-file>
<config-file parent="/*" target="AndroidManifest.xml">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
<source-file src="src/android/FileOpener.java" target-dir="src/fr/smile/cordova/fileopener"/>
<!--以下为新增加的配置-->
<!--增加FileProvider的配置-->
<source-file src="src/android/FileProvider.java" target-dir="src/fr/smile/cordova/fileopener"/>
<config-file target="AndroidManifest.xml" parent="application">
<provider android:name="fr.smile.cordova.fileopener.FileProvider"
android:authorities="${applicationId}.fileOpener2.provider"
android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
</provider>
</config-file>
<source-file src="src/android/res/xml/opener_paths.xml" target-dir="res/xml" />
<!--引用android.support.v4-->
<!--FileProvider继承其中的android.support.v4.content.FileProvider-->
<preference name="ANDROID_SUPPORT_V4_VERSION" default="27.+"/>
<framework src="com.android.support:support-v4:$ANDROID_SUPPORT_V4_VERSION"/>
</platform>
</plugin>
- 配置路径opener_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- https://developer.android.com/reference/android/support/v4/content/FileProvider.html#SpecifyFiles -->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- cordova.file.dataDirectory -->
<files-path name="files" path="." />
<!-- cordova.file.cacheDirectory -->
<cache-path name="cache" path="." />
<!-- cordova.file.externalDataDirectory -->
<external-files-path name="external-files" path="." />
<!-- cordova.file.externalCacheDirectory -->
<external-cache-path name="external-cache" path="." />
<!-- cordova.file.externalRootDirectory -->
<external-path name="external" path="." />
</paths>