今天我們來講一下如何使用Camera來調用照相機掃描二維碼.
(Tips:大神別問我為什麼不用Camera2,飯要一口口吃..慢慢來.其實是我還沒看懂..)
確定一下本篇的學習目標:
1.學會如何調用Camera來實現照相機預覽
2.學會如何跳轉Activity並傳值
3.學會如何識別相機預覽中的二維碼,並讀取
效果圖:
正文
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(),代碼如下(注:這裡是重點):
public void SurfaceCreated(ISurfaceHolder holder)
{
camera = Android.Hardware.Camera.Open();
Android.Hardware.Camera.Parameters p = camera.GetParameters();
p.PictureFormat = ImageFormatType.Jpeg;
camera.SetParameters(p);
camera.SetPreviewCallback(this);
camera.SetPreviewDisplay(holder);
camera.StartPreview();
}
講一下這些代碼做了什麼,首先很明顯..打開照相機.第二句,獲取照相機的參數,設置圖片類型為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了..
相關文章:
原文連結:http://www.cnblogs.com/GuZhenYin/p/7016798.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注公眾號