C#開發移動應用系列(3.使用照相機掃描二維碼+各類基礎知識)

原文: C#開發移動應用系列(3.使用照相機掃描二維碼+各類基礎知識)

前言

上篇文章地址:html

C#開發移動應用系列(1.環境搭建)web

C#開發移動應用系列(2.使用WebView搭建WebApp應用)ide

今天咱們來說一下如何使用Camera來調用照相機掃描二維碼.post

(Tips:大神別問我爲何不用Camera2,飯要一口口吃..慢慢來.....................實際上是我還沒看懂..)學習

肯定一下本篇的學習目標:this

1.學會如何調用Camera來實現照相機預覽spa

2.學會如何跳轉Activity並傳值線程

3.學會如何識別相機預覽中的二維碼,並讀取調試

效果圖:code

 

 

 

正文

1.學會如何調用Camera來實現照相機預覽

   咱們先來看看如何使用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固然就是照相機了..

因此咱們就能夠從這裏一直獲取預覽的圖片幀..(不要心急,慢慢來)

咱們進入第二個知識點

2.學會如何跳轉Activity並傳值

咱們知道,安卓的每個界面轉換都是由一個或者多個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來區分.

這樣,咱們就完成了界面的跳轉和獲取返回值

3.學會如何識別相機預覽中的二維碼,並讀取

下面咱們講講如何讀取相機中的二維碼.

.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了..

相關文章
相關標籤/搜索