DCloud_App_Array
DCloud_App_Array
  • 发布:2014-09-25 19:43
  • 更新:2019-07-08 10:51
  • 阅读:216560

Android平台第三方插件开发指导

分类:HTML5+

欢迎有原生开发能力的朋友入群一起交流学习(入群请提供注册邮箱):
DCloud原生开发者群:
1群:256775471(已满)
2群:814228233

技术架构

HTML5+ 基座扩展采用三层结构,JS层、PluginBridge层和Native层。 三层功能分别是:
JS层: 在Webview页面调用,触发Native层代码,获取执行结果。
PluginBridge层: 将JS层请求进行处理,触发Native层扩展插件代码。
Native层: 插件扩展的平台原生代码,负责执行业务逻辑并执行结果返回到请求页面。


开发者在开发扩展插件时需要为扩展插件编写对应的JS API,JS API将在HTML页面中触发调用对应Native扩展方法的请求,并负责接收运行结果。

开发者在编写扩展插件的JS时需要调用Javascript Plugin Bridge的API用来完成对Native层代码的调用和运行结果的返回。在实际应用中,开发者可以根据扩展方法的实际需求不同,将插件的扩展方法设置为同步执行或异步执行。

同步执行的扩展方法会阻塞当前JS代码的执行,直到Native层插件扩展方法执行完毕。异步扩展方法不会阻塞当前JS代码的执行,使用者需要设置回调方法接收Native层返回的执行结果,开发者需要在插件中调用 Native plugin brigde的方法将执行结果返回到请求页面。

工程示例请参考SDK内包含的HBuilder-Integrate工程,工程里已经整合了插件开发和集成方式的示例。

扩展插件工作流程

异步方法的执行不会阻塞当前JS的运行,方法的执行结果会通过回调的方式返回。
插件异步扩展方法:


同步方法的执行会阻塞当前JS的运行,方法执行完成后可直接获取执行的结果。
插件同步扩展方法:

扩展插件JS API 编写

开发者在实现JS层API时首先要定义一个插件类的别名,并需要在Android工程的assets\data\properties.xml文件中声明插件类别名和Native层扩展插件类的对应关系

<properties>  
    <features>  
        <feature name="plugintest" value="com.example.H5PlusPlugin.PGPlugintest"></feature>  
</properties>  

示例中为方便查看删除了其他插件的代码,开发者在可根据5+应用使用插件的情况进行增删修改。
Feature节点下声明的插件将会在调用时创建相应的对象。

JS扩展方法的实现

同步返回JS扩展方法实现
在实现同步扩展方法时,开发者需要调用JS Plugin Bridge的window.plus.bridge.execSync()
方法,该方法可同步获取Native插件返回的运行结果。

void plus.bridge.execSync( String service, String action, Array<String> args );  

service: 插件类别名
action: 调用Native层插件方法名称。
args: 参数列表。

异步返回JS扩展方法实现
在实现异步扩展方法时,开发者需要调用JS Plugin Bridge的plus.bridge.exec()方法,该方法会通知Native层插件执行指定方法,运行结果会通过回调的方式通知JS层

void plus.bridge.exec( String service, String action, Array<String> args );  

service: 插件类别名
action: 调用Native层插件方法名称。
args: 参数列表。

扩展插件JS API代码示例:

! function(root, factory) {  
    if (typeof exports == 'object' && typeof module != 'undefined') {  
        module.exports = factory()  
    } else if (typeof define == 'function' && define.amd) {  
        define(factory)  
    } else {  
        /**  
         * 插件对象直接扩展到 window 对象上  
         * 这个对象的名字,需要自己填写一下。例如:plugintest  
         */  
        var moduleName = 'plugintest';  
        root[moduleName] = factory()  
    }  
}(this, function() {  
    var _BARCODE = 'plugintest';  
    var plugintest = {  
        PluginTestFunction: function(Argus1, Argus2, Argus3, Argus4, successCallback, errorCallback) {  
            var success = typeof successCallback !== 'function' ? null : function(args) {  
                    successCallback(args);  
                },  
                fail = typeof errorCallback !== 'function' ? null : function(code) {  
                    errorCallback(code);  
                };  
            callbackID = plus.bridge.callbackId(success, fail);  

            return plus.bridge.exec(_BARCODE, "PluginTestFunction", [callbackID, Argus1, Argus2, Argus3, Argus4]);  
        },  
        PluginTestFunctionArrayArgu: function(Argus, successCallback, errorCallback) {  
            var success = typeof successCallback !== 'function' ? null : function(args) {  
                    successCallback(args);  
                },  
                fail = typeof errorCallback !== 'function' ? null : function(code) {  
                    errorCallback(code);  
                };  
            callbackID = plus.bridge.callbackId(success, fail);  
            return plus.bridge.exec(_BARCODE, "PluginTestFunctionArrayArgu", [callbackID, Argus]);  
        },  
        PluginTestFunctionSync: function(Argus1, Argus2, Argus3, Argus4) {  
            return plus.bridge.execSync(_BARCODE, "PluginTestFunctionSync", [Argus1, Argus2, Argus3, Argus4]);  
        },  
        PluginTestFunctionSyncArrayArgu: function(Argus) {  
            return plus.bridge.execSync(_BARCODE, "PluginTestFunctionSyncArrayArgu", [Argus]);  
        }  
    };  
    return plugintest;  
});  

Html使用示例

<!DOCTYPE HTML>  
<html>  
    <head>  
        <meta charset="utf-8"/>  
        <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>  
        <meta name="HandheldFriendly" content="true"/>  
        <meta name="MobileOptimized" content="320"/>  
        <title>H5Plugin</title>  
        <script type="text/javascript" src="./js/common.js"></script>  
        <script type="text/javascript" src="./js/test.js"></script>  
        <script type="text/javascript">  

        function pluginShow() {  
            plus.plugintest.PluginTestFunction("Html5","Plus","AsyncFunction","MultiArgument!", function( result ) {alert( result[0]  + "_" + result[1]  + "_" + result[2]  + "_" + result[3] );},function(result){alert(result)});  
        }  

        function pluginShowArrayArgu() {  
            plus.plugintest.PluginTestFunctionArrayArgu( ["Html5","Plus","AsyncFunction","ArrayArgument!"], function( result ) {alert( result );},function(result){alert(result)});  
        }  

        function pluginGetString()  
        {  
            alert(plus.plugintest.PluginTestFunctionSync("Html5","Plus","SyncFunction","MultiArgument!"));  
        }  

        function pluginGetStringArrayArgu()  
        {  
            var Argus = plus.plugintest.PluginTestFunctionSyncArrayArgu(["Html5","Plus","SyncFunction","ArrayArgument!"]);  
            alert( Argus.RetArgu1 + "_" +  Argus.RetArgu2 + "_" + Argus.RetArgu3  + "_" + Argus.RetArgu4 );  
        }  

        </script>  
        <link rel="stylesheet" href="./css/common.css" type="text/css" charset="utf-8"/>  
    </head>  
    <body>  
        <header>  
            <div class="nvbt" onclick="back();"><div class="iback"></div></div>  
            <div class="nvtt">PluginTest</div>  
        </header>  
        <div id="dcontent" class="dcontent">  
            <br/>  
             <div class="button" onclick="pluginShow()">PluginTestFunction()</div>  
            <div class="button" onclick="pluginShowArrayArgu()">PluginTestFunctionArrayArgu()</div>  
            <div class="button" onclick="pluginGetString()">PluginTestFunctionSync()</div>  
            <div class="button" onclick="pluginGetStringArrayArgu()">PluginTestFunctionSyncArrayArgu()</div>      
            <br/>  
        </div>  
    </body>  
</html>  

uni-app 使用示例
uni-app 中无需主动监听 plusready,可以直接调用 plus 相关的 API。

<template>  
    <view>  
        <button @click="pluginShow">pluginShow</button>  
    </view>  
</template>  
<script>  
// 扩展的 js 文件的位置:common/plugins.js  
    var plugins = require('../../common/plugins.js')  
    export default {  
        data() {  
            return {  
                plugins: plugins  
            };  
        },  
        methods: {  
            pluginShow() {  
                this.plugins.PluginTestFunction("Html5", "Plus", "AsyncFunction", "MultiArgument!", function(result) {  
                    console.log(result[0] + "_" + result[1] + "_" + result[2] + "_" + result[3]);  
                }, function(result) {  
                    console.log(result)  
                });  
            }  
        }  
    }  
</script>  
<style>  

</style>  

Android第三方插件开发指导

准备

首先要下载HTML5+基座的Android版SDK点击下载解压后将HBuilder-Integrate工程导入到ADT中。

uni-app插件开发

android平台:uni-app插件开发

老接口实现方式

开发步骤

创建插件类
开发者创建的扩展插件类应当继承自“IFeature”类实现第三方插件扩展。
创建插件类需要引入的包

import io.dcloud.common.DHInterface.AbsMgr;  
import io.dcloud.common.DHInterface.IFeature;  
import io.dcloud.common.DHInterface.IWebview;  
import io.dcloud.common.util.JSUtil;  

实现接口类的“excute”方法
excute方法负责接收由html页面发起的扩展插件调用请求,并负责根据传入参数运行执行对应的业务。
“execute”方法的“action”参数传入的是JS类的方法名,类型为String。开发者需要在方法中通过字符串匹配来处理请求的逻辑。“pArgs”参数为字符串列表对象,如JS层调用的方法有传入参数,会通过该参数传递到Native的方法中,方法的传入顺序和JS层传入顺序一致。
开发者在实现同步和异步接口运行结果返回时调用的API是不同的
同步执行方法:
同步执行方法在返回结果时可以直接将结果以return的形式返回给js层,返回的结果需要调用

JSUtil.wrapJsVar("Html5 Plus Plugin Hello1!",true);  

处理要返回的字符串,也可调用其他方法处理其他返回值类型(参考io.dclod.util.JSUtil的返回方法)。
异步执行方法:
异步方法开发者需要调用

JSUtil.execCallback(pWebview, cbId, (which==AlertDialog.BUTTON_POSITIVE)?"ok":"cancel", JSUtil.OK, false, false);   

代码实例

package com.example.H5PlusPlugin;  

import io.dcloud.common.DHInterface.AbsMgr;  
import io.dcloud.common.DHInterface.IFeature;  
import io.dcloud.common.DHInterface.IWebview;  
import io.dcloud.common.util.JSUtil;  

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

import android.annotation.SuppressLint;  
import android.annotation.TargetApi;  
import android.os.Build;  

public class PGPlugintest implements IFeature  
{  
    @Override  
    public void init(AbsMgr arg0, String arg1) {  
        // TODO Auto-generated method stub  

    }  

    @SuppressWarnings("deprecation")  
    @TargetApi(Build.VERSION_CODES.CUPCAKE)  
    @SuppressLint("NewApi")  
    @Override  
    public String execute(final IWebview pWebview, final String action, final String[] pArgs) {  
        // TODO Auto-generated method stub  
        //Context context = pWebview.getContext();  

        if ("PluginTestFunction".equals(action))  
        {  
            String CallBackID = pArgs[0];  
            JSONArray newArray = new JSONArray();  
            newArray.put(pArgs[1]);  
            newArray.put(pArgs[2]);  
            newArray.put(pArgs[3]);  
            newArray.put(pArgs[4]);  

            JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, false);  
        }  
        else if("PluginTestFunctionArrayArgu".equals(action))  
        {  
            String ReturnString = null;  
            String CallBackID =  pArgs[0];  
            JSONArray newArray = null;  
            try {  

                newArray = new JSONArray(pArgs[1]);           
                String inValue1 = newArray.getString(0);  
                String inValue2 = newArray.getString(1);  
                String inValue3 = newArray.getString(2);  
                String inValue4 = newArray.getString(3);  
                ReturnString = inValue1 + "-" + inValue2 + "-" + inValue3 + "-" + inValue4;  
            } catch (JSONException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  

            JSUtil.execCallback(pWebview, CallBackID, ReturnString, JSUtil.OK, false);  

        }else if("PluginTestFunctionSync".equals(action))  
        {  
            String inValue1 = pArgs[0];  
            String inValue2 = pArgs[1];  
            String inValue3 = pArgs[2];  
            String inValue4 = pArgs[3];  

            String ReturnValue = inValue1 + "-" + inValue2 + "-" + inValue3 + "-" + inValue4;  
            return JSUtil.wrapJsVar(ReturnValue,true);  

        }else if("PluginTestFunctionSyncArrayArgu".equals(action))  
        {  
            JSONArray newArray = null;  
            JSONObject retJSONObj = null;  
            try {  
                newArray = new JSONArray(pArgs[0]);  
                String inValue1 = newArray.getString(0);  
                String inValue2 = newArray.getString(1);  
                String inValue3 = newArray.getString(2);  
                String inValue4 = newArray.getString(3);  

                retJSONObj = new JSONObject();  
                retJSONObj.putOpt("RetArgu1", inValue1);  
                retJSONObj.putOpt("RetArgu2", inValue2);  
                retJSONObj.putOpt("RetArgu3", inValue3);  
                retJSONObj.putOpt("RetArgu4", inValue4);  

            } catch (JSONException e1) {  
                // TODO Auto-generated catch block  
                e1.printStackTrace();  
            }         

            return JSUtil.wrapJsVar(retJSONObj);  

        }  
        return null;  
    }  

    @Override  
    public void dispose(String arg0) {  
        // TODO Auto-generated method stub  

    }  
}  

新接口实现方式

创建插件类
创建一个继承自StandardFeature的类,实现第三方插件扩展。
创建插件类需要引入的包
import io.dcloud.DHInterface.IWebview;
import io.dcloud.DHInterface.StandardFeature;
import io.dcloud.util.JSUtil;
实现扩展方法
Native层扩展插件的方法名需要和JS Plugin Bridge里windows.plus.bridge.exec()或windows.plus.bridge.execSync()方法的第二个传入参数相同,否则无法调用到指定的方法。

public void PluginTestFunction(IWebview pWebview, JSONArray array)  

扩展方法有两个传入参数
IWebview pWebview 发起请求的webview,
JSONArray array JS请求传入的参数

开发者在实现同步和异步接口运行结果返回时调用的API是不同的
同步执行方法:
同步执行方法在返回结果时可以直接将结果以return的形式返回给js层,返回的结果需要调用

JSUtil.wrapJsVar("Html5 Plus Plugin Hello1!",true);  

处理要返回的字符串,也可调用其他方法处理其他返回值类型(参考io.dclod.util.JSUtil的返回方法)。
异步执行方法:
异步方法开发者需要调用

JSUtil.execCallback(pWebview, cbId, (which==AlertDialog.BUTTON_POSITIVE)?"ok":"cancel", JSUtil.OK, false, false);   

代码示例


package com.example.H5PlusPlugin;  
import io.dcloud.common.DHInterface.IWebview;  
import io.dcloud.common.DHInterface.StandardFeature;  
import io.dcloud.common.util.JSUtil;  

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

public class PGPlugintest extends StandardFeature  
{     
    public void PluginTestFunction(IWebview pWebview, JSONArray array)  
    {  
        String CallBackID = array.optString(0);  
        JSONArray newArray = new JSONArray();  
        newArray.put(array.optString(1));  
        newArray.put(array.optString(2));  
        newArray.put(array.optString(3));  
        newArray.put(array.optString(4));  
        JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, false);  

    }  

    public void PluginTestFunctionArrayArgu(IWebview pWebview, JSONArray array)  
    {  
        String ReturnString = null;  
        String CallBackID =  array.optString(0);  
        JSONArray newArray = null;  
        try {  

            newArray = new JSONArray( array.optString(1));            
            String inValue1 = newArray.getString(0);  
            String inValue2 = newArray.getString(1);  
            String inValue3 = newArray.getString(2);  
            String inValue4 = newArray.getString(3);  
            ReturnString = inValue1 + "-" + inValue2 + "-" + inValue3 + "-" + inValue4;  
        } catch (JSONException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  

        JSUtil.execCallback(pWebview, CallBackID, ReturnString, JSUtil.OK, false);  
    }  

    public String PluginTestFunctionSyncArrayArgu(IWebview pWebview, JSONArray array)  
    {  
        JSONArray newArray = null;  
        JSONObject retJSONObj = null;  
        try {  

            newArray = array.optJSONArray(0);  
            String inValue1 = newArray.getString(0);  
            String inValue2 = newArray.getString(1);  
            String inValue3 = newArray.getString(2);  
            String inValue4 = newArray.getString(3);  

            retJSONObj = new JSONObject();  
            retJSONObj.putOpt("RetArgu1", inValue1);  
            retJSONObj.putOpt("RetArgu2", inValue2);  
            retJSONObj.putOpt("RetArgu3", inValue3);  
            retJSONObj.putOpt("RetArgu4", inValue4);  

        } catch (JSONException e1) {  
            // TODO Auto-generated catch block  
            e1.printStackTrace();  
        }         

        return JSUtil.wrapJsVar(retJSONObj);  
    }  

    public String PluginTestFunctionSync(IWebview pWebview, JSONArray array)  
    {  
        String inValue1 = array.optString(0);  
        String inValue2 = array.optString(1);  
        String inValue3 = array.optString(2);  
        String inValue4 = array.optString(3);  

        String ReturnValue = inValue1 + "-" + inValue2 + "-" + inValue3 + "-" + inValue4;  
        return JSUtil.wrapJsVar(ReturnValue,true);  
    }  

}  

三 关联JS插件名和原生类

在编写扩展插件时需要修改“/assets/data”中properties.xml文件,在其中添加JS对象名称和Android包的类名对应关系,SDK会根据对应的类名查找并生成相应的对象并执行对应的逻辑。


在应用的manifest.json文件中还需要添加扩展插件的应用使用权限

Android平台插件开发API

io.dcloud.DHInterface.IFeature

扩展插件接口类,Android平台的扩展插件应当继承自此接口类并实现接口方法。

常用方法说明:

String execute(IWebview pWebView, String action, String[] pArgs);  

执行扩展插件的方法,调用native代码实现具体的操作。
pWebView: 扩展插件方法运行的窗口
action: 调用插件方法的名称
args: 调用插件方法使用的参数列表

io.dcloud.util.JSUtil

常用方法说明:

String wrapJsVar(String value, boolean isString);  

转换JS层的返回值,也用于异步接口中回调函数的参数。
参数说明:
value: 要返回到JS层的值
isString:返回值类型是否为原始字符串
返回方法:
boolea类型: wrapJSVar( "true", false );
Number类型: wrapJsVar( "99", false );
String类型: wrapJsVar( "hello", true );
数组类型: wrapJsVar( "[1,2,3,4,5]", false );
JSON类型: wrapJsVar( "{'name':'value'}", false );

String execCallback(IWebview pWebView, String pCallbackId, String pMessage, int pStatus, boolean isJson, boolean pKeepCallback);  

触发扩展插件中的回调方法。

参数说明:
pWebView:扩展插件方法运行的窗口
pCallbackId:回调函数的唯一标识
pMessage:回调函数的参数
pStatus:操作是否成功,成功则使用JSUtil.OK,否则使用错误代码
isJson:回调函数参数是否为JSON数据
pKeepCallback:是否可多次触发回调函数

术语字典

JS Plugin Bridge: H5+ Plugin Bridge层JS部分API,用户通过调用相应的API触发Native层扩展插件相应方法的调用。
Native Plugin Bridge: H5+ Plugin Bridge层Native部分API,开发者通过实现接口类方法,实现由JS层触发Native层扩展插件逻辑。开发者调用API实现Native扩展方法运行结果得返回。
Native层插件:开发者使用原生语言实现的5+扩展插件,可被JS层通知调用。
插件类别名:JS层字符串,用来声明JS方法和Native层插件的对应关系

IOS平台开发第三发插件请参考

IOS平台第三发插件开发指导

10 关注 分享
可怜的光头强 green85 Mosaic9 Trust 小山三夏 liuhongyang_1@sina.com gaohuazi 犹行犹予 pingzi_kendy@qq.com 844189873@qq.com

要回复文章请先登录注册

lixing0323@163.com

lixing0323@163.com

回复 765199214@qq.com:
你好,如何把android做成插件,求教。。。能否加个QQ...
2019-07-08 10:51
lixing0323@163.com

lixing0323@163.com

能否做个demo,然后大家参考做就ok了。。
2019-07-06 11:58
1246009209@qq.com

1246009209@qq.com

回复 175840715@qq.com:
这个问题是的,提个问题,半天爱理不理的。假如官方大大心情好回答你起来也是和踢皮球一样,不知道官方这样有什么劲
2019-06-06 10:32
1599535330@qq.com

1599535330@qq.com

能不能在编辑搞一个插件导入功能呢,这特么太难了,看不懂java代码,要是会java,都直接上原生的呢,好用这打包个啥
2019-05-06 18:02
844189873@qq.com

844189873@qq.com

这里面有个坑,关于启动白屏的,官方文档没提到。
就是:如果AndroidManifest.xml文件当中manifest节点下的package如果和build.gradle文件当中的applicationId不一致,启动的时候就会白屏
2019-03-23 23:46
g417317028@163.com

g417317028@163.com

这个文档貌似过期了,有没有新的文档或者案例。
2018-11-16 18:15
504346513@qq.com

504346513@qq.com

看懂是看懂了,但是官方demo运行起来,不能正常工作,不知道为啥
2018-11-02 16:26
375890534@qq.com

375890534@qq.com

回复 花生先生:
确实,刚去看了一下隔壁,各种插件都有人开发啊
2018-10-09 15:20
861366490@qq.com

861366490@qq.com

这文档我也是醉了。都不说jar包怎么和新建类关联起来,jar包是直接放到libs里吗?
2018-10-07 12:48
Linton

Linton

写的什么文档?怎么打包到项目里?我用过apicloud,比这个好用,还好意思跟人家打官司,我就呵呵了
2018-09-23 16:48
花生先生

花生先生

回复 175840715@qq.com:
很多dcloud没有的插件,apicloud都有付费方案,有时候宁愿付费的,几百块钱总比自己折腾好几天强!
2018-09-01 08:59
花生先生

花生先生

回复 jackyting@126.com:
好像是要注册到service里面去
2018-09-01 08:57
花生先生

花生先生

回复 505757015@qq.com:
说到心坎上了,根本不考虑新手,有些需要重点关注的应该重点标注出来的,往往一些小细节会耽误你一天两天!
2018-09-01 08:56
jaydon007@163.com

jaydon007@163.com

感觉能开发插件的都可以写原生程序了。。。
2018-08-13 11:58
jackyting@126.com

jackyting@126.com

android中onstart()方法不执行的吧,在json文件和xml文件都配置了,onstart()里面的log都没打印,但是点击html页面中按钮又可以调用里面的方法的,
2018-07-28 16:33
1051852598@qq.com

1051852598@qq.com

写的还不错,就是版本太老了,更新一下容易看懂些
2018-07-27 16:45
452306705@qq.com

452306705@qq.com

新插件 在 onstart 的时候,也就是初始化的时候 怎么返回数据给js层啊
2018-07-26 17:05
505757015@qq.com

505757015@qq.com

这个文档,对于没接触过安卓的人来说,最起码要结合原生看30遍以上,才能略微看懂- -
2018-07-04 17:35
765199214@qq.com

765199214@qq.com

刚开始看插件开发文档时是懵逼的,最后尝试使用插件制作了异步蓝牙oad升级插件、蓝牙设备操作插件等,到后来的加密信息插件、读取文件插件、清理计算手机缓存插件,到今天再看插件开发,觉得吧,写的真心不错,也是难为开发人员了,至少我写的话写不出这么详细的文档
2018-06-29 21:39
Marco

Marco

终于完成一个Facebook登录的插件了,这教程不是一般人能看懂啊!!
2018-06-22 16:52
175840715@qq.com

175840715@qq.com

回复 175840715@qq.com:
真不想爆粗口,但看了这文档就真心忍不住爆了,如果你们听不见批评意见,那就没得说了,你们没精力搞插件提供平台,可以找别人弄啊。2-3个开发人员搞不定么?开始配置1个android、1个ios 一个插件一个插件的开发 发布到专门的插件平台让人能用收费免费你们拿捏下不就完了?你们本就提倡h5+js开发app,那能来的又多少是android与ios全懂的,像我这种只懂android不懂ios的咋搞?以为所有公司android与ios全配置??愿意集结组织的android与ios人员赞同的开发人员请举手,我建议自发组织个插件平台,直接找dcloud商量,赞同的同志们顶起。
2018-05-27 01:55
175840715@qq.com

175840715@qq.com

看了这个写的文档只想说句mmp 写的啥鸡巴文档,技术牛逼能把文档先整理清楚吗?文档都整理不清楚别人能用?你技术牛逼别人能看到?整体说其他平台抄袭你,但别人就是抄袭你做得好啊,文档乱七八糟,本来说开发下插件,一看这屌几把文档就不想看了,能认真点?你免费是好事,但是好事要么做好要么不做,做不好会被骂做得好被赞扬,这就是根本,这就是社会。你让别人开源插件,呢你开源插件的平台呢?或者你直接提供一个专门支持发布插件的地方也行啊。让人能看啊,收费都可以啊,你这样去收费开发者也乐于使用啊。搞不懂,有心思成天打官司,能好好搞搞自己平台?你们策划是吃屎的,产品经理是吃屎长大的
2018-05-27 01:49
羊腰子

羊腰子

回复 羊腰子:
已解决
还是老问题,plusready加载时机不对
我的测试方式:
js中加日志,示例中方式outLine(变量信息)
发现新定义的插件对象为空
又在plusready中加了桥接插件定义的日志,发现没有日志输出

得到结论是plusready没执行
最后找到文章

http://ask.dcloud.net.cn/article/165
已进入断点但是邮件没发
2018-02-01 08:34
羊腰子

羊腰子

回复 羊腰子:
@DCloud_SDK_骁骑
这种问题如何测试,不知道问题出在哪
2018-01-31 12:18
羊腰子

羊腰子

js通过老接口的方式调用插件,但是没有反应。我调用的是mail.jar,用于自动发送邮件,android studio走断点没有反应,Log.v打印日志也没有输出 @DCloud_SDK_骁骑
2018-01-31 08:35
765199214@qq.com

765199214@qq.com

回复 乐小唱:
我蓝牙部分也是这样,onactivityresult没有执行,你的找到方法了吗
2018-01-09 11:26
765199214@qq.com

765199214@qq.com

使用插件,异步回调H5必须alert吗?我把alert注释掉后,并未执行成功回调后的document.getElementById('lock').innerText = "OPENED";
2018-01-08 23:45
240044537@qq.com

240044537@qq.com

回复 梁大路:
这个问题有答案了吗?
2017-12-18 17:36
zjkuki@21cn.com

zjkuki@21cn.com

为啥就不直接用cordova的底层框架呢?H5+插件开发方式跟cordova的方法差不多,移植cordova插件过来要大改,mui做轻应用还是可以的,偏偏就那么最后一公里路没走好!
2017-12-04 22:05
745760410@qq.com

745760410@qq.com

http://blog.csdn.net/u010978381 可以看看博客
2017-10-09 10:40
zb305107@163.com

zb305107@163.com

请问使用插件和直接调用原生代码有什么区别?
2017-09-01 11:59
fly_sky

fly_sky

回复 fly_sky:
import io.dcloud.common.DHInterface.IWebview;
import io.dcloud.common.DHInterface.StandardFeature;
import io.dcloud.common.util.JSUtil;
2017-09-01 09:09
fly_sky

fly_sky

新接口实现方式

创建插件类
创建一个继承自StandardFeature的类,实现第三方插件扩展。
创建插件类需要引入的包
import io.dcloud.DHInterface.IWebview;
import io.dcloud.DHInterface.StandardFeature;
import io.dcloud.util.JSUtil;
这是老的接口方式吧。新的jar引入后在android studio会报错的。


应该是:
import io.dcloud.DHInterface.IWebview;
import io.dcloud.DHInterface.StandardFeature;
import io.dcloud.util.JSUtil;
2017-09-01 09:08
958979436@qq.com

958979436@qq.com

JSUtil.execCallback(mpWebview, CallBackID, ReturnString, JSUtil.OK, false,true);
这里这个execCallback提示说过期了,然而文档并没有给出替代品。。。
2017-08-09 10:33
梁大路

梁大路

请问什么叫老接口什么叫新接口,是针对什么方面说的
2017-07-19 17:21
JJww

JJww

你好,请问下 如何解决插件模式下 实现IFeature或继承StandardFeature 无法调用onCreate 实现主线程问题?
2017-07-18 18:09
15850679227@163.com

15850679227@163.com

回复 dreamlwj:
请问现在有方法了吗,刚入坑的·小白......
2017-07-17 21:36
15850679227@163.com

15850679227@163.com

回复 331319769@qq.com:
请问现在是不是不能将jar导入来引用
2017-07-17 21:26
ppbear_ly@163.com

ppbear_ly@163.com

插件中不能自己开启线程吗? 我每次开启程序就直接崩溃退出!
2017-07-11 17:20
古芗

古芗

这种的是不是只能离线 打包
2017-06-23 13:18
asdf330901@163.com

asdf330901@163.com

建议学习一下写作
2017-06-16 16:08
自然简单

自然简单

IFeature 过期了?要用什么?
2017-06-01 11:52
欢乐的饲养员

欢乐的饲养员

慢慢看,能看懂的,要用心
2017-05-31 17:43
幽壑潜蛟

幽壑潜蛟

真是一脸懵逼。不知道说的是啥
2017-05-13 16:19
乐小唱

乐小唱

IApp iApp = iWebview.obtainFrameView().obtainApp();
iApp.registerSysEventListener(new ISysEventListener() {
@Override
public boolean onExecute(SysEventType sysEventType, Object o) {
System.out.println("5555555555555555");


return true;
}
}, SysEventType.onActivityResult);
试了这个方法没有成功
2017-05-06 20:44
乐小唱

乐小唱

安卓viewpager里面集成sdk_webapp,导致子activity(sdk_webapp)中onactivityresult方法不执行,以至于调用相册没有回调怎么解决呢,,,急
2017-05-06 20:43
豆豆宝贝

豆豆宝贝

mark一下
2017-04-19 09:52
叶寒

叶寒

在插件中如何启动Activity啊?
2017-03-17 14:00
285887933@qq.com

285887933@qq.com

使用 Vue 或者Angular配合Dcould 该怎么开发呢
2017-03-01 17:00
wHolmes1992

wHolmes1992

回复 Calow:
现在确定能实现吗,我也在质疑这个问题
2017-02-23 17:08
SDK_骁骑

SDK_骁骑

回复 zhang6339:
js层传入参数的顺序就是在原生层插件里JSonArray获取参数的顺序
2017-02-14 22:54
zhang6339

zhang6339

方法里面JSONArray类型的参数,在调用方法时应该对应什么,一直没搞懂,希望懂的大牛能够指条路。不胜感激。
2017-02-13 19:44
331319769@qq.com

331319769@qq.com

继续来补坑:调用自定义插件方法报not found自定义的方法。
文章开篇讲了导5个包,有个json的包,恰好插件方法中第二个参数是JSONArray,当时第一反应就是把之前的那个json包import进来,结果试了n遍,一直报找不到方法。最后无奈只能看导的包是否一致,结果发现demo中导的是import org.json.JSONArray; 真心坑爹!!希望遇到该问题的同学能够看到。
2017-01-21 01:55
331319769@qq.com

331319769@qq.com

还是有点懵,重点应该是如果使用非官方的插件(自己写或者第三方),就必须自己离线打包(也就是自己用ADT或者AS导入基座项目添加插件与HBuilder写好的h5代码生成apk),我是这么理解的。很多人认为写插件就是封装成一个jar包,然后在HBuilder中导入,不过在评论中貌似好像看到官方说目前只支持离线打包(可能是考虑了第三方插件的安全问题吧,毕竟在线打包是在他们服务器那端生成apk)。
2017-01-20 01:59
cyq7on

cyq7on

回复 Calow:
lz解决没,我调用getDPluginActivity为空,有个initDPlugin(Context var1, Activity var2)方法,但是不知道怎么传activity进去
2017-01-09 17:43
767921813@qq.com

767921813@qq.com

android的第三方插件能不能启动activity
2016-12-06 10:18
moon小Z

moon小Z

大神们 由于badparam无法分享到微信 是怎么回事儿 求解 小弟感激不尽
2016-11-22 11:54
liuyusijie@hotmail.com

liuyusijie@hotmail.com

您好,请问我写的插件层一调用厂商的类系统就自动闪退是为什么呢?
另外我想使用message传递消息的话在h5的插件开发中要怎么做呢?
之前用原生安卓的时候是在activity层中new JSInterface的时候把handler 和context 传递过去,加载我们第三方插件的时候是不用传这两个参数的。
感谢。
2016-11-15 14:17
1440053982@qq.com

1440053982@qq.com

回复 磊子:
太感谢了,求加好友qq1440053982
2016-11-09 23:18
Shinobu

Shinobu

回复 34482836@qq.com:
R类是android工程自动生成的,不可改动,这么说吧,在android里每定义一个变量或者控件什么的,在R类里都有对应它的一个int值
2016-10-21 18:16
智联创想

智联创想

彻底懵了
2016-09-11 00:28
34482836@qq.com

34482836@qq.com

请问:HBuilder-Integrate工程中,io.dcloud.RInformation类用到了一个名为R的类中的属性,全为int类型或int数组,R类是自己编写?能否提供一个参考,属性都应该如何设置。
2016-09-09 15:24
767921813@qq.com

767921813@qq.com

回复 cjj_coder:
大神,Hbuilder调用蓝牙的插件怎么写
2016-08-15 15:11
书痕

书痕

你们什么感觉我不知道,反正我看得云里雾里的,最近想做一个手持终端APP,他们扫码和打印有对应的SDK,想集成进来,但看了这么一篇东西后我是彻底糊涂了,连基本原理都没明白——是第三方SDK集成到HTML5+基座里还是反过来?改那么多地方的原因是什么?做出来的插件怎么集成到自己项目里?
下载的HTML5+基座SDK中有好多文件夹和文件,我都不知道分别是做什么的,里面的readme写得忒简单,想找到自己要的东西很艰难。
虽然你们可能不愿意听,不过在这方面我看到Ionic好像更简单——借用node命令操作,先用plugman初始化一个插件,在对应java文件里写写自己的代码,然后用plugin add加入自己的项目中,最后在项目js文件中通过cordova.plugins.xxx调用即可。我觉得原理和这里应该差不多,但这个真的好乱。
2016-08-10 16:02
asdfasfsa

asdfasfsa

这么多人反映看不懂,官方不会处理一下,出点视频什么的详细教程,讲的不明不白的
2016-08-02 10:16
qixi

qixi

mark
2016-08-01 11:20
进击的狗蛋丶

进击的狗蛋丶

回复 SDK_骁骑:
在PGPlugintest 这个类的哪个方法调用第三方jar的方法呢
2016-07-29 10:51
BrianChen

BrianChen

该示例展示了用Hbuilder怎么集成第三方插件,那么可不可以用Hbuilder发布第三方插件呢?有相关示例或教程吗
2016-07-12 11:29
werwolf

werwolf

回复 SDK_骁骑:
默认示例中有添加,但是也是不可以的。
2016-06-20 16:46
zzsj@vip.qq.com

zzsj@vip.qq.com

感觉直接提供HBuilder-Integrate工程不太适合新手,应该有一个详细的关于如果建立自己的“HBuilder-Integrate”工程,这样对新人会很有帮助呢。
2016-06-02 18:07
SDK_骁骑

SDK_骁骑

回复 362816692@qq.com:
最好能把插件的代码发一下,这个错误输出看不出什么问题来
2016-05-11 11:33
362816692@qq.com

362816692@qq.com

写了一个插件报下面的错是怎么回事???
05-10 09:36:23.672: W/cr.BindingManager(25143): Cannot call determinedVisibility() - never saw a connection for the pid: 25143
2016-05-10 09:39
杰世

杰世

新手问下 HBuilder-Integrate导入 eclipse中了 可是我怎么运行 查看PGPlugintest的 效果啊!直接运行进入的是ActivityEntry,然后选择三个集成方式, 里面也有没有 关于这个地方的查看啊!
2016-03-24 16:35
bozai

bozai

回复 SDK_骁骑:
现在谷歌大力发展Android studio工具,是否有相关的使用指导??
2016-01-27 13:21
SDK_骁骑

SDK_骁骑

回复 Oslanka:
你看下这个文档最下边的常见问题,应该可以解决你的问题
http://ask.dcloud.net.cn/article/508
2016-01-22 11:02
Oslanka

Oslanka

回复 wenfor:
怎么解决了??
2016-01-21 11:41
花花去骑车

花花去骑车

做过完整原生开发的表示很难看懂
2016-01-05 22:46
小郭哥

小郭哥

回复 trytest:
http://ask.dcloud.net.cn/article/103
2016-01-05 14:12
小郭哥

小郭哥

我也是没看太懂,建议再弄个详细讲解的文章,或者做个视频教程。毕竟这个功能太重要了
2016-01-04 13:49
SDK_骁骑

SDK_骁骑

回复 wenfor:
私信你了 你看下
2015-12-30 16:55
wenfor

wenfor

为什么我在eclipse能写的插件,而在androidstudio中用同样的方法做就不行呢,完全没有进入反射的类里面
2015-12-30 15:57
Laster

Laster

回复 dreamlwj:
同问~我已经看到很多问这个的了,官方现在对于这个问题一律不回答! 目前只看http://ask.dcloud.net.cn/question/13908 这个说法比较靠谱
2015-12-23 17:59
dreamlwj

dreamlwj

回复 wiloon:
同问
2015-12-22 14:25
dreamlwj

dreamlwj

回复 hyhezhen:
你好,我在学习原生插件的开发,插件写了,不知道怎么用eclipse打包(主要是不知道打包要求),然后怎么放到我的hbuilder工程里使用,倒是知道怎么用js调用,但是打好的包该以什么形式放到哪个文件夹,做什么关联,命名有什么要求,就完全不知道了,能否告知一下怎么做?
2015-12-22 14:24
dreamlwj

dreamlwj

回复 cjj_coder:
请教下怎么把写好的原生插件放入到hbuilder的工程里使用?
2015-12-22 11:55
SDK_骁骑

SDK_骁骑

回复 滚滚长江:
自己开发的插件只能用SDK离线打包,暂时还不能在线打包
2015-11-30 16:46
滚滚长江

滚滚长江

回复 SDK_骁骑:
你好, 我想自己做个插件功能,怎样才能打包进来呢 ?
2015-11-28 23:01
woshilijixiang

woshilijixiang

我是看的云里雾里的 不知道有哪位大仙看懂的 指导指导
2015-11-24 11:15
dci

dci

回复 SDK_骁骑:
webview集成方式
2015-11-11 22:14
SDK_骁骑

SDK_骁骑

回复 dci:
你用的什么集成方式?
2015-11-11 18:18
dci

dci

你好。我按照教程写好了插件,得到了预想的效果。只是在Hbuilder中写的编译的工程,放到assert目录中,某些页面跳转会有问题。比如在main.html中使用document.location.href = "input.html"会提示file:///android_assets/.....找不到路径,而在Hbuilder中是正常的。希望能得到帮助,不胜感激啊!
2015-11-11 11:41
trytest

trytest

HBuilder-Integrate项目在哪里能找到呢?在创建移动APP中的选择模板中没有发现。
2015-10-29 17:45
磊子

磊子

回复 SDK_骁骑:
第三方lib集成问题已经解决,是so文件位置的问题,我把so文件在armeabi、armeabi-v7a、x86这3个目录中都放上就可以调用。
2015-10-29 12:32
SDK_骁骑

SDK_骁骑

回复 磊子:
Phonegap的插件是不能直接在H5+的基座里用的,需要根据5+插件的规范对接口进行下调整
2015-10-27 21:06
磊子

磊子

回复 SDK_骁骑:
第三方的lib在原生的程序调用都正常,但做成插件后就不能调用,是不是html+的插件机制与phonegap的插件机制不同,我以前在phonegap中做的插件是可以调用这个lib的。
2015-10-27 13:33
SDK_骁骑

SDK_骁骑

回复 磊子:
如果需要调用第三方的lib,就需要通过写普通插件,在普通插件的Native代码中调用第三方的lib里的function
2015-10-21 16:19
磊子

磊子

我按照上面步骤开发出来的插件普通的插件是没有问题的,但是调用第三方的lib时就不行,有谁遇到过给指点一下。
2015-10-12 19:22
jolynekujo

jolynekujo

我导入了HBuilder-Integrate,里面新建了一个类作为android第三方插件类,另外的js插件文件和html文件直接放到assets\apps\H5Plugin\www里面对应的文件夹里,怎么整合起来?
2015-10-10 15:39
hyhezhen

hyhezhen

我前面提的一个问题,已经有办法了,http://ask.dcloud.net.cn/question/8850

现在基本会写原生插件来支持上层的调用了。 希望 原生SDK的文档,实例能更多些(http://www.dcloud.io/docs/sdk/android/), 也希望能给出些(原生)UI插件插件的参考
2015-09-02 09:40
hyhezhen

hyhezhen

定制原生底层可以触发WEBVIEW的(自定义)事件吗?
比如我希望 双方SOCKET通讯,HTML5启动底层函数发送数据后并不关闭SOCKET,底层持续监听。 每次收到新数据后,触发事件和返回数据给上层。这样HTML层可以刷新页面的数据内容
(而不是只异步执行一次),这个可以做到吗?
2015-08-29 11:51