您的位置:首页 > 其它

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

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

       好了开始正题吧。

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

navigator.device.capture.captureImage(   

<span style="white-space:pre">  </span>CaptureCB captureSuccess, CaptureErrorCB captureError, [CaptureImageOptions options]  

);  
     
    里面有三个参数,前两个分别是代表调用成功,调用失败的回调函数,第三个是条件限制,但是只有是limit和mode的参数,分别表示的意义如下:

limit: 在单个采集操作期间能够采集的图像数量最大值,必须设定为大于等于1(默认值为1)。  

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去。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐