上篇文章地址: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了..