編輯:關於Android編程
目前的很多應用上都有掃碼功能,當時微信推出二維碼掃碼功能時,覺得imagine,通過一張簡單的圖片就能掃描添加還有,還有分享名片功能(也是一張二維碼圖片,識別掃描)。
下面小編將通過文章主要介紹QRCode方面技術.
QRCode是被廣泛應用的一種二維碼,解碼速度快。二維碼相對於條形碼來說,二維碼的存儲數據量更大,空間利用率高,有一定的容錯性。
二維碼原理介紹:
二維碼是用某種特定的幾何圖形按一定的規律在平面上分布的黑白相間的圖形記錄數據符號信息的;
在代碼編制上巧妙的利用構成計算機內部邏輯基礎的0/1比特流的概念,使用若干個與二進制相對應的幾何形體來表示文字數值信息,通過圖像輸入設備或光電掃描設備自動識讀以實現信息自動處理;
二維碼能夠在橫向和縱向兩個方位同時表達信息,因此能在很小的面積內表達大量的信息;
二維碼相對於條形碼的優勢就是省空間;
QRCode基本結構
上圖是一個QRCode的基本結構:
位置探測圖形、位置探測圖形分隔符、定位圖形:用於二維碼的定位,對每個QR來說,位置都是固定存在的,只是大小規格有所差異;
校正圖形:確定規格,校正圖形的數量和位置也就確定了;
格式信息:表示二維碼的糾錯級別,分為L、M、Q、H;
版本信息:即二維碼的規格,QR碼符號共有40種規格的矩陣;
數據和糾錯碼字:實際保存的二維碼信息,和糾錯碼字(用於修正二維碼損壞帶來的錯誤)。
條形碼原理介紹:
條形碼掃描器結構
由於不同顏色的物體,其反射的可見光的波長不同,所以當條形碼掃描器光源發出的光經光闌及凸透鏡1後,照射到黑白相間的條形碼上時,反射光經凸透鏡2聚焦後,照射到光電轉換器上,於是光電轉換器接受到與白條和黑條相對應的強弱不同的反射光信號,並轉換成相應的電信號輸出到放大整形電路,整形電路把模擬信號轉換成數字電信號,再經譯碼接口電路譯成數字字符信息。
整形電路的脈沖數字信號經譯碼器譯成數字、字符信息.它通過識別起始、終止字符來判別出條形碼符號的碼制及掃描方向;通過測量脈沖數字電信號0、1的數目來判別出條和空的數目.通過測量0、1信號持續的時間來判別條和空的寬度.這樣便得到了被辯讀的條形碼符號的條和空的數目及相應的寬度和所用碼制,根據碼制所對應的編碼規則,便可將條形符號換成相應的數字、字符信息,通過接口電路送給計算機系統進行數據處理與管理,便完成了條形碼辨讀的全過程。
二、Zxing使用原理介紹
Zxing是一個開源的,用於Java實現的多種格式的1D/2D條碼圖像處理庫,它包含了聯系到其他語言的接口。
Zxing可以實現使用手機的內置攝像頭完成條形碼和二維碼的掃描與解碼。
Zxing可以實現條形碼和二維碼的編碼與解碼。
Zxing目前支持的格式如下:UPC-A、UPC-E、EAN-8、EAN-13、39碼、93碼、代碼128、QR碼。
1.導入Zxing.jar包,直接將源碼內的com.mining.app.zxing.camera,com.mining.app.zxing.decoding, com.mining.app.zxing.view, com.mining.app.zxing.encoding四個文件夾,zxing package直接復制到你的工程目錄下。
源碼下載地址:http://code.google.com/p/zxing/
GitHub下載地址:https://github.com/zxing/zxing
2.將raw文件(用於),values,權限以及資源文件,全部准備完全,詳情可參見源碼。
3. activity.xml主菜單布局文件
4.activity_capture.xml掃描布局文件
<framelayout android:layout_height="fill_parent" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"></framelayout>
5.activity_title.xml Title布局文件
上述文件用於
6.MainActivity.java.主界面用於事件的處理
package example.com.zxingdemo; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.google.zxing.WriterException; import zxing.encoding.EncodingHandler; public class MainActivity extends Activity { private final static int SCANNIN_GREQUEST_CODE = 1; /** * 顯示掃描結果 */ private TextView mTextView ; /** * 顯示掃描拍的圖片 */ private ImageView mImageView; /** * 輸入框產生二維碼 * @param savedInstanceState */ private EditText qrStrEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.result); mImageView = (ImageView) findViewById(R.id.qrcode_bitmap); qrStrEditText = (EditText) findViewById(R.id.et_qr_string); //點擊按鈕跳轉到二維碼掃描界面,這裡用的是startActivityForResult跳轉 //掃描完了之後調到該界面 Button mButtonScan = (Button) findViewById(R.id.button1); Button mBtnTwoCode = (Button) findViewById(R.id.button2); Button mBtnOneCode = (Button) findViewById(R.id.button3); mButtonScan.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setClass(MainActivity.this, MipcaActivityCapture.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivityForResult(intent, SCANNIN_GREQUEST_CODE); } }); //產生二維碼 mBtnTwoCode.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String contentString = qrStrEditText.getText().toString(); try { if (!contentString.equals("")) { Bitmap qrCodeBitmap = EncodingHandler.createQRCode(contentString, 350); mImageView.setImageBitmap(qrCodeBitmap); qrStrEditText.setText(""); mTextView.setText(contentString); } else { Toast.makeText(getApplicationContext(), "Text can be not empty", Toast.LENGTH_SHORT).show(); } } catch (WriterException e) { e.printStackTrace(); } } }); //產生條形碼 mBtnOneCode.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String contentString = qrStrEditText.getText().toString(); int size = contentString.length(); for (int i = 0; i < size; i++) { int c = contentString.charAt(i); if ((19968 <= c && c < 40623)) { Toast.makeText(getApplicationContext(), "text not be chinese", Toast.LENGTH_SHORT).show(); return; } } Bitmap mBmpOneCode = null; try { if (contentString != null && !"".equals(contentString)) { mBmpOneCode = EncodingHandler.CreateOneDCode(contentString); qrStrEditText.setText(""); mTextView.setText(contentString); } } catch (WriterException e) { e.printStackTrace(); } if (mBmpOneCode != null) { mImageView.setImageBitmap(mBmpOneCode); } } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case SCANNIN_GREQUEST_CODE: if(resultCode == RESULT_OK){ Bundle bundle = data.getExtras(); //顯示掃描到的內容 mTextView.setText(bundle.getString("result")); //顯示 mImageView.setImageBitmap((Bitmap) data.getParcelableExtra("bitmap")); } break; } } }
7.MipcaActivityCapture.java.主要是調用起Camera功能進行掃描
package example.com.zxingdemo; import android.app.Activity; import android.content.Intent; import android.content.res.AssetFileDescriptor; import android.graphics.Bitmap; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.os.Bundle; import android.os.Handler; import android.os.Vibrator; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import com.google.zxing.BarcodeFormat; import com.google.zxing.Result; import java.io.IOException; import java.util.Vector; import zxing.camera.CameraManager; import zxing.decoding.CaptureActivityHandler; import zxing.decoding.InactivityTimer; import zxing.view.ViewfinderView; /** * Initial the camera * @author Ryan.Tang */ public class MipcaActivityCapture extends Activity implements Callback { private CaptureActivityHandler handler; private ViewfinderView viewfinderView; private boolean hasSurface; private VectordecodeFormats; private String characterSet; private InactivityTimer inactivityTimer; private MediaPlayer mediaPlayer; private boolean playBeep; private static final float BEEP_VOLUME = 0.10f; private boolean vibrate; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_capture); //ViewUtil.addTopView(getApplicationContext(), this, R.string.scan_card); CameraManager.init(getApplication()); viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); Button mButtonBack = (Button) findViewById(R.id.button_back); mButtonBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { MipcaActivityCapture.this.finish(); } }); hasSurface = false; inactivityTimer = new InactivityTimer(this); } @Override protected void onResume() { super.onResume(); SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view); SurfaceHolder surfaceHolder = surfaceView.getHolder(); if (hasSurface) { initCamera(surfaceHolder); } else { surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } decodeFormats = null; characterSet = null; playBeep = true; AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE); if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) { playBeep = false; } initBeepSound(); vibrate = true; } @Override protected void onPause() { super.onPause(); if (handler != null) { handler.quitSynchronously(); handler = null; } CameraManager.get().closeDriver(); } @Override protected void onDestroy() { inactivityTimer.shutdown(); super.onDestroy(); } /** * 處理掃描結果 * * @param result * @param barcode */ public void handleDecode(Result result, Bitmap barcode) { inactivityTimer.onActivity(); playBeepSoundAndVibrate(); String resultString = result.getText(); if (resultString.equals("")) { Toast.makeText(MipcaActivityCapture.this, "Scan failed!", Toast.LENGTH_SHORT).show(); } else { Intent resultIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putString("result", resultString); bundle.putParcelable("bitmap", barcode); resultIntent.putExtras(bundle); this.setResult(RESULT_OK, resultIntent); } MipcaActivityCapture.this.finish(); } private void initCamera(SurfaceHolder surfaceHolder) { try { CameraManager.get().openDriver(surfaceHolder); } catch (IOException ioe) { return; } catch (RuntimeException e) { return; } if (handler == null) { handler = new CaptureActivityHandler(this, decodeFormats, characterSet); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { if (!hasSurface) { hasSurface = true; initCamera(holder); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { hasSurface = false; } public ViewfinderView getViewfinderView() { return viewfinderView; } public Handler getHandler() { return handler; } public void drawViewfinder() { viewfinderView.drawViewfinder(); } private void initBeepSound() { if (playBeep && mediaPlayer == null) { // The volume on STREAM_SYSTEM is not adjustable, and users found it // too loud, // so we now play on the music stream. setVolumeControlStream(AudioManager.STREAM_MUSIC); mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setOnCompletionListener(beepListener); AssetFileDescriptor file = getResources().openRawResourceFd( R.raw.beep); try { mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength()); file.close(); mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME); mediaPlayer.prepare(); } catch (IOException e) { mediaPlayer = null; } } } private static final long VIBRATE_DURATION = 200L; private void playBeepSoundAndVibrate() { if (playBeep && mediaPlayer != null) { mediaPlayer.start(); } if (vibrate) { Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); vibrator.vibrate(VIBRATE_DURATION); } } /** * When the beep has finished playing, rewind to queue up another one. */ private final OnCompletionListener beepListener = new OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mediaPlayer.seekTo(0); } }; }
1.生成二維碼
調用方法:
//產生二維碼 mBtnTwoCode.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String contentString = qrStrEditText.getText().toString(); try { if (!contentString.equals("")) { Bitmap qrCodeBitmap = EncodingHandler.createQRCode(contentString, 350); mImageView.setImageBitmap(qrCodeBitmap); qrStrEditText.setText(""); mTextView.setText(contentString); } else { Toast.makeText(getApplicationContext(), "Text can be not empty", Toast.LENGTH_SHORT).show(); } } catch (WriterException e) { e.printStackTrace(); } } });
實現方法:
private static final int BLACK = 0xff000000; //生成二維碼 public static Bitmap createQRCode(String str,int widthAndHeight) throws WriterException { Hashtablehints = new Hashtable (); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); BitMatrix matrix = new MultiFormatWriter().encode(str, BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight); int width = matrix.getWidth(); int height = matrix.getHeight(); int[] pixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (matrix.get(x, y)) { pixels[y * width + x] = BLACK; } } } Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
2.生成條形碼
調用方法:
//產生條形碼 mBtnOneCode.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String contentString = qrStrEditText.getText().toString(); int size = contentString.length(); for (int i = 0; i < size; i++) { int c = contentString.charAt(i); if ((19968 <= c && c < 40623)) { Toast.makeText(getApplicationContext(), "text not be chinese", Toast.LENGTH_SHORT).show(); return; } } Bitmap mBmpOneCode = null; try { if (contentString != null && !"".equals(contentString)) { mBmpOneCode = EncodingHandler.CreateOneDCode(contentString); qrStrEditText.setText(""); mTextView.setText(contentString); } } catch (WriterException e) { e.printStackTrace(); } if (mBmpOneCode != null) { mImageView.setImageBitmap(mBmpOneCode); } } });
實現方法:
//生成條形碼 public static Bitmap CreateOneDCode(String content) throws WriterException { // 生成一維條碼,編碼時指定大小,不要生成了圖片以後再進行縮放,這樣會模糊導致識別失敗 BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.CODE_128, 500, 200); int width = matrix.getWidth(); int height = matrix.getHeight(); int[] pixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (matrix.get(x, y)) { pixels[y * width + x] = BLACK; } } }
3.掃描二維碼、條形碼
mButtonScan.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setClass(MainActivity.this, MipcaActivityCapture.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivityForResult(intent, SCANNIN_GREQUEST_CODE); } });
一、環境分離簡介每個App項目,至少都會有兩個環境:測試環境和生產環境。多的甚至有四個環境:開發環境、測試環境、預生產環境和生產環境。開發人員經常需要在環境之間切換,測試
上次簡單地介紹了AudioRecord和AudioTrack的使用,這次就結合Surf
魅族MX6已發布了,除了漂亮的外觀,MX6還帶來了一項重磅功能:微信指紋支付(此前已經支持支付寶)。那魅族微信指紋支付是怎麼支付的呢?下文就讓小編跟大家魅族
Heap Viewer,Memory Monitor和Allocation Tracker是用來可視化你的app使用內存的補充工具。使用Memory Monitor To