cordova通过原生实现自定义功能

原创 2016年10月04日 13:38:15


        先闲谈说下最近的微信要出的小程序吧,感觉确实很牛逼,革命说不上吧但是也是一个新的大的机遇。不得不承认腾讯有两个相当好的平台,一个是QQ,一个是微信,毕竟人数基数大,任何新的东西都会带来相当多的机会和挑战。那个小程序好像是基于react native,也是一种混合架构。最近整理整理下混合架构的知识,有时间也好好学习去。

       好了开始正题吧。

       最近研究cordova通过原生实现自定义功能也是因为客户的一些需求吧,客户提出了要连拍的功能,而cordova自定义的接口里,代码是这样的:

  1. navigator.device.capture.captureImage(   
  2. <span style="white-space:pre">  </span>CaptureCB captureSuccess, CaptureErrorCB captureError, [CaptureImageOptions options]  
  3. );  
     
    里面有三个参数,前两个分别是代表调用成功,调用失败的回调函数,第三个是条件限制,但是只有是limit和mode的参数,分别表示的意义如下:

  1. limit: 在单个采集操作期间能够采集的图像数量最大值,必须设定为大于等于1(默认值为1)。  
  2. mode: 选定的图像模式,必须设定为capture.supportedImageModes枚举中的值。  

    如此一来,每次默认是调用了原生自带的相机,效果就和原生的这句一样:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 

    达不到客户的需求,于是只好想想在原生里自己写一个这样的效果。其实这个需求难度并不大,但是自己在这方便也只是一个菜鸟,于是重新好好学习了下,这里很感谢一篇博文,还是一个妹子写的,写得非常详细,地址是:
    http://blog.csdn.net/tangjiarao/article/details/48288875
    
    具体方法应该很清楚了。然后我以我自己的例子说下我的流程吧:
    1.Cordova里按钮的点击事件,主要是写好回调函数,将回调的值(相片地址)记录并写入预定地方加载展示出来:
function test(){
    var suc= function(message) {
        loadpic(message)
    };
    navigator.test.fun(0,suc);
}

function loadpic(message){
    var i, len;
    var str = '';
    var mFiles= new Array();
    mFiles= message.split(',');
    for (i = 0, len = mFiles.length; i < len; i++) {
        var path = mFiles[i];
        var array_index = fullPathArray.length ;
        fullPathArray[array_index] = path;
        str += '<li class="pic_li"><img src="'+ path +'"></li>';
    }
    // 显示拍摄的照片
    $("#largeImage").append(str);
    loadImgJs();
}
   2.在js里把设置好来回传的参数和方法。
{
        "file": "plugins/intent.js",
        "id": "org.apache.cordova.Test",
        "merges": [
        "navigator.test"
        ]
        },
cordova.define("org.apache.cordova.Test", function(require, exports, module) {

        var exec = require('cordova/exec');

        module.exports = {

        fun: function(mills,suc) {
        exec(suc, null, "IntentPlugin", "test", [mills]);
        },
        };
        });
   3.在CordovaPlugin里设置好来回传的参数和方法。
else if(action.equals("test")){
        intent=new Intent(cordova.getActivity(),TakePicActivity.class);
        }
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {

        super.onActivityResult(requestCode, resultCode, intent);
        //传递返回值 给js方法
        switch(resultCode){
            case Activity.RESULT_OK:
                Bundle b=intent.getExtras();
                String str=b.getString("hi");

                //通过PluginResult和callbackContext返回给js接口  
                PluginResult pluginResults = new PluginResult(PluginResult.Status.OK, str);
                callbackContext.sendPluginResult(pluginResults);
                pluginResults.setKeepCallback(true);
                callbackContext.success();

        }

    }
}
   4.在原生里通过surfaceview实现连拍并传回照片保存地址
public class TakePicActivity extends Activity implements SurfaceHolder.Callback{
    private static final String TAG = "TestCameraActivity";
    public static final String KEY_FILENAME = "filename";
    private ImageView iv;
    private SurfaceView sv;
    private Camera mCamera;
    private String mFileName;
    private int i=1;
    private String str="";
    private Intent mIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_takepic);
        iv=(ImageView)findViewById(R.id.takephoto);
        sv=(SurfaceView)findViewById(R.id.my_surfaceView);
        mIntent=this.getIntent();
        SurfaceHolder holder = sv.getHolder();
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        holder.addCallback(this); // 回调接口
        Toast.makeText(this, "正在拍摄第1张照片", Toast.LENGTH_LONG).show();

        iv.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if(i<4){
                    mCamera.takePicture(mShutter, null, mJpeg);
                }
            }
        });


    }

    /* 图像数据处理还未完成时的回调函数 */
    private Camera.ShutterCallback mShutter = new Camera.ShutterCallback() {
        @Override
        public void onShutter() {
            // 一般显示进度条
        }
    };

    /* 图像数据处理完成后的回调函数 */
    @SuppressLint("SdCardPath")
    private Camera.PictureCallback mJpeg = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // 保存图片
            mFileName = UUID.randomUUID().toString() + ".jpg";
            Log.i(TAG, mFileName);
            try {
                String sdStatus = Environment.getExternalStorageState();
                String name = DateFormat.format("yyyyMMdd_hhmmss",Calendar.getInstance(Locale.CHINA)) + ".jpg";
                Bitmap oldBitmap = BitmapFactory.decodeByteArray(data, 0,
                        data.length);
                Matrix matrix = new Matrix();
                matrix.setRotate(90);
                Bitmap newBitmap = Bitmap.createBitmap(oldBitmap, 0, 0,
                        oldBitmap.getWidth(), oldBitmap.getHeight(),
                        matrix, true);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                newBitmap.compress(Bitmap.CompressFormat.JPEG, 85, baos);
                FileOutputStream b = null;
                File file = new File("/sdcard/Image/");
                file.mkdirs();// 创建文件夹
                String fileName = "/sdcard/Image/"+name;
                str=str+fileName+",";

                try {
                    b = new FileOutputStream(fileName);
                    newBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把数据写入文件
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        b.flush();
                        b.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            i++;

            try {
                if(i<4){
                    mCamera.startPreview();
                    Toast.makeText(TakePicActivity.this, "正在拍摄第"+i+"张照片", Toast.LENGTH_LONG).show();
                }else{
                    str=str.substring(0,str.length()-1);
                    mIntent.putExtra("hi", str);
                    setResult(RESULT_OK, mIntent);
                    finish();
                }
            } catch (Exception e) {
                if (mCamera != null) {
                    mCamera.release();
                    mCamera = null;
                }
            }
        }
    };

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
        // SurfaceView尺寸发生改变时(首次在屏幕上显示同样会调用此方法),初始化mCamera参数,启动Camera预览

        Parameters parameters = mCamera.getParameters();// 获取mCamera的参数对象
        Size largestSize = getBestSupportedSize(parameters
                .getSupportedPreviewSizes());
        parameters.setPreviewSize(largestSize.width, largestSize.height);// 设置预览图片尺寸
        largestSize = getBestSupportedSize(parameters
                .getSupportedPictureSizes());// 设置捕捉图片尺寸
        parameters.setPictureSize(largestSize.width, largestSize.height);
        mCamera.setParameters(parameters);

        try {
            mCamera.startPreview();
        } catch (Exception e) {
            if (mCamera != null) {
                mCamera.release();
                mCamera = null;
            }
        }

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // SurfaceView创建时,建立Camera和SurfaceView的联系
        if (mCamera != null) {
            try {
                mCamera.setPreviewDisplay(holder);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // SurfaceView销毁时,取消Camera预览
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }

    @SuppressLint("NewApi")
    @Override
    public void onResume() {
        super.onResume();
        // 开启相机
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            mCamera = Camera.open(0);
            // i=0 表示后置相机
        } else
            mCamera = Camera.open();
    }

    @Override
    public void onPause() {
        super.onPause();
        // 释放相机
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }

    }

    private Size getBestSupportedSize(List<Size> sizes) {
        // 取能适用的最大的SIZE
        Size largestSize = sizes.get(0);
        int largestArea = sizes.get(0).height * sizes.get(0).width;
        for (Size s : sizes) {
            int area = s.width * s.height;
            if (area > largestArea) {
                largestArea = area;
                largestSize = s;
            }
        }
        return largestSize;
    }
}

    如此通过原生的activity实现了自定义的效果并通过两次回调实现了数据的回传。不过感觉cordova的效果确实很一般,有时间学习下react native去。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Cordova 原生插件编写总结

简单
  • u012230445
  • u012230445
  • 2017年04月20日 09:57
  • 297

cordova开发介绍(android平台)

本文主要介绍android平台下cordova的开发环境,包含其各配置文件,plugin的开发等等,并且提供一个简单示例以供参考。...
  • sproll
  • sproll
  • 2016年03月16日 12:44
  • 7543

cordova之自定义插件

1)html页面引入cordova.js,android项目引用cordova.jar或者加载CordovaLib 2)自定义一个类继承CordovaPlugin,例如public class MyP...
  • wxx1471181824
  • wxx1471181824
  • 2016年12月12日 13:41
  • 342

微信小程序集成Redux

原文地址:示例先展示成果Redux是什么 Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 Redux官方文档为什么要使用Redux小程序俨然是一个类似Hybrid App...
  • shooter32
  • shooter32
  • 2016年10月09日 16:24
  • 2285

Cordova自定义插件,解决Android混合开发向原生开发的过渡

关键词:混合开发 ionic-2.1.4 + cordova-6.3.1 + angularJS Cordova 自定义插件 插件源码:Cordova自定义插件源码 今天说...
  • xinluqishi123
  • xinluqishi123
  • 2017年02月25日 09:00
  • 739

如何在原生工程中引入Cordova工程

如今混合开发方兴未艾,有的项目可能一开始是原生开发的,后期需要加入混合开发,如将Cordova工程引进到原生工程中。那么该如何操作呢?下面就来描述一下步骤。 1、首先我们来创建一个Cordova工程,...
  • E20914053
  • E20914053
  • 2015年12月04日 09:28
  • 4593

cordova混合移动app调试工具GapDebug+ripple emulate

Ripple Emulate 使用Google模拟器,可以帮到大部分的调试 GapDebug 真机安装apk,电脑端和真机端同步调试 适用的项目 phonegap/cordova ioni...
  • lucy_100
  • lucy_100
  • 2015年11月13日 16:58
  • 6507

各种不同的开关按钮,有原生的,有自定义的

  • 2015年06月30日 17:50
  • 2.13MB
  • 下载

Cordova自定义插件实战

Cordova自定义插件实战完成Toast,拨打电话,发送短信的插件编写
  • hbl_for_android
  • hbl_for_android
  • 2016年07月10日 12:57
  • 4856

Cordova4.3.1 android 自定义插件(显示土司Toast)

自定义插件步骤: 1,
  • yuhailong626
  • yuhailong626
  • 2014年06月11日 16:12
  • 12954
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:cordova通过原生实现自定义功能
举报原因:
原因补充:

(最多只允许输入30个字)