上篇文章地址:html
C#开发移动应用系列(2.使用WebView搭建WebApp应用)ide
今天咱们来说一下如何使用Camera来调用照相机扫描二维码.post
(Tips:大神别问我为何不用Camera2,饭要一口口吃..慢慢来.....................实际上是我还没看懂..)学习
肯定一下本篇的学习目标:this
1.学会如何调用Camera来实现照相机预览spa
2.学会如何跳转Activity并传值线程
3.学会如何识别相机预览中的二维码,并读取调试
效果图:code
咱们先来看看如何使用Camera来实现照相机预览..
咱们首先新建一个Activity,...嗯..暂且命名为SaoYiSaoActivity (不是骚..是扫..)
在Resources\layout 建立对应的界面,SaoYiSao.axml
在SaoYiSaoActivity的OnCreate中加载这个页面,代码以下:
protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.SaoYiSao); }
在SaoYiSao.axml中拖入控件SurfaceView,这里的SurfaceView是用来展现预览画面的..(具体的SurfaceView做用自行百度..或者等我下篇..)
一样,咱们把它铺满全屏,如图:
下面咱们开始写代码...
由于咱们要调用照相机和监控SurfaceView.因此咱们的SaoYiSaoActivity 须要继承一些东西,代码以下:
public class SaoYiSaoActivity : Activity,Android.Hardware.Camera.IPreviewCallback,ISurfaceHolderCallback
须要继承Android.Hardware.Camera.IPreviewCallback来获取照相机的预览回调
须要继承ISurfaceHolderCallback来获取SurfaceView发生在表面的事件和变化
咱们实现这两个接口,会获得以下几个方法
OnPreviewFrame(),来自于Android.Hardware.Camera.IPreviewCallback
SurfaceChanged()
SurfaceCreated()
SurfaceDestroyed()
咱们一个一个来实现,
不过在此以前,先回到OnCreate()方法中,初始化一下咱们的SurfaceView
编写代码以下:
protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.SaoYiSao); //获取surfaceView1 var surface = FindViewById<SurfaceView>(Resource.Id.surfaceView1); //获取surface的线程 var holder = surface.Holder; //设置线程回调为本类 holder.AddCallback(this); //代表该Surface不包含原生数据 holder.SetType(Android.Views.SurfaceType.PushBuffers); //设置这个Surface的大小 holder.SetFixedSize(300, 200); }
解释都在注释里了..我就很少说了..
下面开始实现刚才的接口..
首先来实现 SurfaceCreated(),代码以下(注:这里是重点):
1 public void SurfaceCreated(ISurfaceHolder holder) 2 { 3 camera = Android.Hardware.Camera.Open(); 4 Android.Hardware.Camera.Parameters p = camera.GetParameters(); 5 p.PictureFormat = ImageFormatType.Jpeg; 6 camera.SetParameters(p); 7 camera.SetPreviewCallback(this); 8 camera.SetPreviewDisplay(holder); 9 camera.StartPreview(); 10 11 12 }
讲一下这些代码作了什么,首先很明显..打开照相机.第二句,获取照相机的参数,设置图片类型为Jpeg.从新把参数赋值给照相机.
设置照相机的预览回调为自身类,设置照相机显示为SurfaceView的线程
最后,开始预览.
而后咱们实现SurfaceDestroyed(),这里是当Surface被销毁以前调用的方法,代码以下(注:也很重要):
public void SurfaceDestroyed(ISurfaceHolder holder) { //删除回调 holder.RemoveCallback(this); //删除照相机回调 camera.SetPreviewCallback(null); //中止照相机预览 camera.StopPreview(); //释放照相机 camera.Release(); camera = null; }
必定要写这些,否则照相机会一直处于占用状态..而后GG..
实现上面两个方法.其实咱们就能够调用照相机预览了...
OnPreviewFrame()这个方法,咱们暂时先不实现 放个空的.打个断点
运行,咱们会发现.OnPreviewFrame()这个方法会被不停的调用.
里面有两个参数
public void OnPreviewFrame(byte[] data, Android.Hardware.Camera camera)
很明显,这个字节类型的data就是每次照相机预览传回来的当前帧的图片信息.
camera固然就是照相机了..
因此咱们就能够从这里一直获取预览的图片帧..(不要心急,慢慢来)
咱们进入第二个知识点
咱们知道,安卓的每个界面转换都是由一个或者多个Activity实现的..
前面咱们也单独写了一个SaoYiSaoActivity
那么咱们该如何跳转过去呢..往下看..
咱们在MainActivity添加一个Button,给他添加一个点击事件,代码以下:
btn2.Click += delegate { Intent intent = new Intent(this,typeof(SaoYiSaoActivity)); intent.AddFlags(ActivityFlags.SingleTop); StartActivityForResult(intent, 1); };
用SaoYiSaoActivity类型申明一个Intent ,
而后添加Activity启动模式,为SingleTop.
由于咱们要获取SaoYiSaoActivity传递回来的参数,因此咱们采用StartActivityForResult来跳转.
第一个参数固然就是要跳转的Intent ,第二个是获取返回值用的Code编号(注意:要大于0)
这样咱们就实现了跳到SaoYiSaoActivity..
那么如何获取SaoYiSaoActivity给的返回值呢?.
咱们重写Activity的OnActivityResult方法,以下:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); //若是当初的发的requestCode =1 if (requestCode == 1 && resultCode == Result.Ok) { webView.LoadUrl(data.GetStringExtra("code")); Toast.MakeText(this, "扫描结果:" + data.GetStringExtra("code"), ToastLength.Short).Show(); } }
你们能够看到,上面咱们有一个判断requestCode==1,这个1就是咱们传递过去的第二个参数.
当你有多个跳转界面的时候,就能够用这个requestCode来区分.
这样,咱们就完成了界面的跳转和获取返回值
下面咱们讲讲如何读取相机中的二维码.
.Net解析二维码,在个人知识储备里面...经常使用的只有2个库,一个是QRCode,一个是ZXing.Net.(PS:若是有大神知道更好的,请留言赐教..)
很遗憾QRCode,使用的是GDI+ 也就是System.drawing..很明显..咱们在手机端..调用不到..
因此只能用ZXing.Net
咱们在nuget中搜索ZXing.Net.
如图:
类型不少..并且有各类版本..咱们选择ZXing.Net.Mobile,
固然这里还有个ZXing.Net.Mobile.Forms,这个是封装好的二维码扫描控件..本文主要是学习,因此不使用(固然..你主要是实现功能..就用这个..巨人的肩膀上 多刺激..).
咱们首先定义一个方法CodeDecoder来专门解析二维码,代码以下:
/// <summary> /// 二维码解码 /// </summary> /// <returns></returns> public string CodeDecoder(byte[] data,int width,int height) { byte[] bytes = data;//获取图片字节 //设置位图源 PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, width, height, 0, 0, width,height, false); //处理像素值内容信息 BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); //初始化解析器 ZXing.Reader reader = new QRCodeReader(); //解析位图 ZXing.Result result = reader.decode(bitmap); if (result == null) return null; return result.Text;//返回解析结果 }
前面咱们说过了.OnPreviewFrame()是照相机预览的回调.因此咱们如今就来实现他.
代码以下:
public void OnPreviewFrame(byte[] data, Android.Hardware.Camera camera) { try { //获取相机宽度 int previewWidth = camera.GetParameters().PreviewSize.Width; //获取相机高度 int previewHeight = camera.GetParameters().PreviewSize.Height; //解析二维码 var date = CodeDecoder(data, previewWidth, previewHeight); //判断是否解析到二维码. if (date != null) { //跳转回主页面 Intent intent = new Intent(this, typeof(MainActivity)); //放入一个key 为code 的解析后的值 intent.PutExtra("code", date); //状态设为OK SetResult(Android.App.Result.Ok, intent); //关闭当前界面 Finish(); } } catch (IOException) { } }
上面的代码,if中的代码就是如何跳转回主界面,而且传递返回值.
最后咱们用百度的网址,生成一个二维码,调试,扫描..就是前面的效果图拉~
感受不少东西..其实基本和JAVA都是同样的..
因此不要抱怨Xamarin的资料少..你能查到相关的JAVA资料..基本也就搞定Xamarin了..