Android开发怎么实现模仿360二维码扫描功能
小编给大家分享一下Android开发怎么实现模仿360二维码扫描功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
具体如下:
一、效果图:
二、框架搭建
首先,下载最新zxing开源项目。 下载地址:http://code.google.com/p/zxing/
或 点击此处本站下载。
分析项目结构,明确扫描框架需求。在zxing中,有很多其他的功能,项目结构比较复杂;针对二维码QRCode扫描,我们需要几个包:
(1)com.google.zxing.client.android.Camera 基于Camera调用以及参数配置,核心包
(2)DecodeFormatManager、DecodeThread、DecodeHandler 基于解码格式、解码线程、解码结果处理的解码类
(3)ViewfinderView、ViewfinderResultPointCallBack 基于取景框视图定义的View类
(4)CaptureActivity、CaptureActivityHandler 基于扫描Activity以及扫描结果处理的Capture类
(5)InactivityTimer、BeepManager、FinishListener 基于休眠、声音、退出的辅助管理类
(6)Intents、IntentSource、PrefrencesActivity 基于常量存储的常量类
新建工程,添加如下权限permission:
<uses-permission android:name="android.permission.CAMERA"/><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.FLASHLIGHT" />
添加core.jar文件,并BuildPath;将上述类或包加入工程后,会报一系列错误,原因有几点:
(1)资源文件缺乏,将zxing下需要的资源文件copy到新工程下
(2)版本兼容问题,zxing下很多技术都是使用4.0版本及以上,集成到低版本之后,须做相应改动,详情参照项目源码
(3)包结构引用问题,需要重新导入包引用
最后框架
三、具体实现
创建MainActivity用于跳转到扫描页面
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)); } }); }}
布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/btn_scan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="@color/white" android:padding="20dp" android:background="@drawable/btn_scan_result" android:text="扫一扫" /> <include android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" layout="@layout/activity_scan_title" /></RelativeLayout>
扫描页面
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; private ViewfinderView mFindView; private CaptureActivityHandler mHandler; private boolean hasSurface; private Vector<BarcodeFormat> mDecodeFormats; 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); } @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); // 如果当前是铃音模式,则继续准备下面的 蜂鸣提示音操作,如果是静音或者震动模式。就不要继续了。因为用户选择了无声的模式,我们就也不要出声了。 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; } // 关闭摄像头信息 CameraManager.get().closeDriver(); } @Override protected void onDestroy() { // 关闭定时器 inactivityTimer.shutdown(); super.onDestroy(); } 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 { //扫描完成后传递结果 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) { } @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) { // 设置声道流格式为音乐 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); // 第一个参数,指代一个震动的频率数组。每两个为一组,每组的第一个为等待时间,第二个为震动时间。 // 比如 [2000,500,100,400],会先等待2000毫秒,震动500,再等待100,震动400 // 第二个参数,repest指代从 第几个索引(第一个数组参数) 的位置开始循环震动。 // 会一直保持循环,我们需要用 vibrator.cancel()主动终止 // vibrator.vibrate(new long[]{300,500},0); } } private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mediaPlayer.seekTo(0); } };}
布局文件
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <SurfaceView android:id="@+id/preview_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" /> <com.android.scan.view.ViewfinderView android:id="@+id/viewfinder_view" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <include android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" layout="@layout/activity_scan_title" /> </RelativeLayout></FrameLayout>
结果页面
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); } } }); //设置图片信息 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开发怎么实现模仿360二维码扫描功能”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341