小編給大家分享一下Android開發(fā)怎么實現(xiàn)模仿360二維碼掃描功能,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)是專業(yè)的淶源網(wǎng)站建設(shè)公司,淶源接單;提供成都網(wǎng)站制作、做網(wǎng)站,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進行淶源網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
具體如下:
一、效果圖:
二、框架搭建
1、首先,下載最新zxing開源項目。 下載地址:http://code.google.com/p/zxing/
或 點擊此處本站下載。
2、分析項目結(jié)構(gòu),明確掃描框架需求。在zxing中,有很多其他的功能,項目結(jié)構(gòu)比較復(fù)雜;針對二維碼QRCode掃描,我們需要幾個包:
(1)com.google.zxing.client.android.Camera 基于Camera調(diào)用以及參數(shù)配置,核心包
(2)DecodeFormatManager、DecodeThread、DecodeHandler 基于解碼格式、解碼線程、解碼結(jié)果處理的解碼類
(3)ViewfinderView、ViewfinderResultPointCallBack 基于取景框視圖定義的View類
(4)CaptureActivity、CaptureActivityHandler 基于掃描Activity以及掃描結(jié)果處理的Capture類
(5)InactivityTimer、BeepManager、FinishListener 基于休眠、聲音、退出的輔助管理類
(6)Intents、IntentSource、PrefrencesActivity 基于常量存儲的常量類
3、新建工程,添加如下權(quán)限permission:
4、 添加core.jar文件,并BuildPath;將上述類或包加入工程后,會報一系列錯誤,原因有幾點:
(1)資源文件缺乏,將zxing下需要的資源文件copy到新工程下
(2)版本兼容問題,zxing下很多技術(shù)都是使用4.0版本及以上,集成到低版本之后,須做相應(yīng)改動,詳情參照項目源碼
(3)包結(jié)構(gòu)引用問題,需要重新導(dǎo)入包引用
5、最后框架
三、具體實現(xiàn)
1、創(chuàng)建MainActivity用于跳轉(zhuǎn)到掃描頁面
/** * 二維碼掃描 * @Project App_ZXing * @Package com.android.scan * @author chenlin * @version 1.0 * @Date 2014年3月6日 */ public class MainActivity extends Activity { private Button mBtnScan; private Button mBtnBack; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtnBack = (Button) findViewById(R.id.btn_back); mBtnBack.setVisibility(View.GONE); mBtnScan = (Button) findViewById(R.id.btn_scan); mBtnScan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, ScanActivity.class)); } }); } }
布局文件
2、掃描頁面
/** * 條形碼掃描 * * @Project App_ZXing * @Package com.android.scan * @author chenlin * @version 1.0 * @Date 2014年3月6日 */ public class ScanActivity extends Activity implements Callback { private static final float BEEP_VOLUME = 0.10f; protected static final String RESULT_TEXT = "result"; protected static final String RESULT_BITMAP = "bitmap"; /** 掃描界面 */ private SurfaceView mSurfaceView; /** 自定義的View,就是我們看見的拍攝時中間的框框了 */ private ViewfinderView mFindView; /** 解碼處理類,負(fù)責(zé)調(diào)用另外的線程進行解碼。 */ private CaptureActivityHandler mHandler; /** 判斷是否創(chuàng)建了SurfaceView */ private boolean hasSurface; /** decodeFormats 條形碼,二維碼等的集合 */ private VectormDecodeFormats; /** 字符編碼 */ private String characterSet; /** 定時器 */ private InactivityTimer inactivityTimer; /** 媒體播放器 */ private MediaPlayer mediaPlayer; /** 是否播放聲音 */ private boolean playBeep; /** 是否震動 */ private boolean vibrate; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan); init(); } /** * 初始化 */ private void init() { mSurfaceView = (SurfaceView) findViewById(R.id.preview_view); mFindView = (ViewfinderView) findViewById(R.id.viewfinder_view); CameraManager.init(getApplication()); hasSurface = false; inactivityTimer = new InactivityTimer(this); } /** * 暫停后恢復(fù)時處理內(nèi)容 */ @SuppressWarnings("all") @Override protected void onResume() { super.onResume(); // 先重新獲得holder SurfaceHolder surfaceHolder = mSurfaceView.getHolder(); if (hasSurface) { initCamera(surfaceHolder); } else { surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } mDecodeFormats = null; characterSet = null; playBeep = true; AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE); // 如果當(dāng)前是鈴音模式,則繼續(xù)準(zhǔn)備下面的 蜂鳴提示音操作,如果是靜音或者震動模式。就不要繼續(xù)了。因為用戶選擇了無聲的模式,我們就也不要出聲了。 if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) { playBeep = false; } // 初始化播放聲音 initBeepSound(); //播放 vibrate = true; } @Override protected void onPause() { super.onPause(); if (mHandler != null) { mHandler.quitSynchronously(); mHandler = null; } // 關(guān)閉攝像頭信息 CameraManager.get().closeDriver(); } @Override protected void onDestroy() { // 關(guān)閉定時器 inactivityTimer.shutdown(); super.onDestroy(); } /** * 處理掃描結(jié)果 * * @param result * @param barcode */ public void handleDecode(Result result, Bitmap barcode) { // 添加定時器 inactivityTimer.onActivity(); // 響鈴和震動 playBeepSoundAndVibrate(); String resultString = result.getText(); if (TextUtils.isEmpty(resultString)) { ToastUtil.show(this, "掃描失敗"); ScanActivity.this.finish(); } else { //掃描完成后傳遞結(jié)果 Intent resultIntent = new Intent(); resultIntent.setClass(ScanActivity.this, ScanResultActivity.class); resultIntent.putExtra(RESULT_TEXT, resultString); ByteArrayOutputStream baos = new ByteArrayOutputStream(); barcode.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] bitmapByte = baos.toByteArray(); resultIntent.putExtra(RESULT_BITMAP, bitmapByte); startActivity(resultIntent); overridePendingTransition(R.anim.activity_in_from_rigth, R.anim.activity_out_to_scale); ScanActivity.this.finish(); } } private void initCamera(SurfaceHolder surfaceHolder) { try { CameraManager.get().openDriver(surfaceHolder); } catch (IOException ioe) { return; } catch (RuntimeException e) { return; } if (mHandler == null) { mHandler = new CaptureActivityHandler(this, mDecodeFormats, characterSet); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * 在視圖創(chuàng)建的時候初始化攝像頭 */ @Override public void surfaceCreated(SurfaceHolder holder) { if (!hasSurface) { hasSurface = true; initCamera(holder); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { hasSurface = false; } public ViewfinderView getViewfinderView() { return mFindView; } public Handler getHandler() { return mHandler; } public void drawViewfinder() { mFindView.drawViewfinder(); } /** * 初始化聲音資源 */ private void initBeepSound() { // 如果要播放聲音并且沒有播放器時 if (playBeep && mediaPlayer == null) { // 設(shè)置聲道流格式為音樂 setVolumeControlStream(AudioManager.STREAM_MUSIC); mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); // 設(shè)置聲音完成后監(jiān)聽 mediaPlayer.setOnCompletionListener(beepListener); // 設(shè)定數(shù)據(jù)源,并準(zhǔn)備播放 AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.beep); try { mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength()); file.close(); mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);// 設(shè)置音量 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); // 第一個參數(shù),指代一個震動的頻率數(shù)組。每兩個為一組,每組的第一個為等待時間,第二個為震動時間。 // 比如 [2000,500,100,400],會先等待2000毫秒,震動500,再等待100,震動400 // 第二個參數(shù),repest指代從 第幾個索引(第一個數(shù)組參數(shù)) 的位置開始循環(huán)震動。 // 會一直保持循環(huán),我們需要用 vibrator.cancel()主動終止 // vibrator.vibrate(new long[]{300,500},0); } } /** * 注冊事件。當(dāng)播放完畢一次后,重新指向流文件的開頭,以準(zhǔn)備下次播放。 */ private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mediaPlayer.seekTo(0); } }; }
布局文件
3、結(jié)果頁面
/** * * @Project App_ZXing * @Package com.android.scan * @author chenlin * @version 1.0 * @Date 2014年3月6日 * @Note TODO */ public class ScanResultActivity extends Activity { private EditText mEtScan; private Button mBtnBack; private Button mBtnCopy; private ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan_result); initViews(); init(); } private void init() { final String result = getIntent().getStringExtra(ScanActivity.RESULT_TEXT); mEtScan.setText(result); final ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); mBtnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ScanResultActivity.this.finish(); } }); mBtnCopy.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (result!=null) { ClipData myClip = ClipData.newPlainText("text", result); cm.setPrimaryClip(myClip); } } }); //設(shè)置圖片信息 byte[] imgByte = getIntent().getByteArrayExtra(ScanActivity.RESULT_BITMAP); if (imgByte != null) { Drawable drawable = BitmapUtil.byte2Drawable(imgByte); if (drawable != null) { mImageView.setImageDrawable(drawable); } } } // public void paste(View view){ // ClipData abc = myClipboard.getPrimaryClip(); // ClipData.Item item = abc.getItemAt(0); // String text = item.getText().toString(); // pasteField.setText(text); // Toast.makeText(getApplicationContext(), "Text Pasted", // Toast.LENGTH_SHORT).show(); // } private void initViews() { mEtScan = (EditText) findViewById(R.id.et_scan_result); mBtnBack = (Button) findViewById(R.id.btn_back); mBtnCopy = (Button) findViewById(R.id.btn_copy); } }
以上是“Android開發(fā)怎么實現(xiàn)模仿360二維碼掃描功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!