Zxing掃描和生成二維碼+butterknife8.0之後的引用
**最近項目中用到二維碼掃描和生成使用到了Zxing這裏記錄下來:
先貼官方地址:**官網地址 開源中國 github.
項目下載地址:http://download.csdn.net/detail/u010023795/9679251
- 我這裏只集成了掃碼和二維碼生成的功能這裏主要用到的兩個類:CaptureActivity 掃描和EncodingUtils生成:“
* /*
public final class CaptureActivity extends Activity implements SurfaceHolder.Callback {private static final String TAG = CaptureActivity.class.getSimpleName();
private CameraManager cameraManager;
private CaptureActivityHandler handler;
private InactivityTimer inactivityTimer;
private BeepManager beepManager;private SurfaceView scanPreview = null;
private RelativeLayout scanContainer;
private RelativeLayout scanCropView;
private ImageView scanLine;private Rect mCropRect = null;
private boolean isHasSurface = false;public Handler getHandler() {
return handler;
}public CameraManager getCameraManager() {
return cameraManager;
}@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.activity_capture); scanPreview = (SurfaceView) findViewById(R.id.capture_preview); scanContainer = (RelativeLayout) findViewById(R.id.capture_container); scanCropView = (RelativeLayout) findViewById(R.id.capture_crop_view); scanLine = (ImageView) findViewById(R.id.capture_scan_line); inactivityTimer = new InactivityTimer(this); beepManager = new BeepManager(this); TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation .RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.9f); animation.setDuration(4500); animation.setRepeatCount(-1); animation.setRepeatMode(Animation.RESTART); scanLine.startAnimation(animation);
}
@Override
protected void onResume() {
super.onResume();// CameraManager must be initialized here, not in onCreate(). This is // necessary because we don't // want to open the camera driver and measure the screen size if we're // going to show the help on // first launch. That led to bugs where the scanning rectangle was the // wrong size and partially // off screen. cameraManager = new CameraManager(getApplication()); handler = null; if (isHasSurface) { // The activity was paused but not stopped, so the surface still // exists. Therefore // surfaceCreated() won't be called, so init the camera here. initCamera(scanPreview.getHolder()); } else { // Install the callback and wait for surfaceCreated() to init the // camera. scanPreview.getHolder().addCallback(this); } inactivityTimer.onResume();
}
@Override
protected void onPause() {
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
inactivityTimer.onPause();
beepManager.close();
cameraManager.closeDriver();
if (!isHasSurface) {
scanPreview.getHolder().removeCallback(this);
}
super.onPause();
}@Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}@Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
Log.e(TAG, “* WARNING * surfaceCreated() gave us a null surface!”);
}
if (!isHasSurface) {
isHasSurface = true;
initCamera(holder);
}
}@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isHasSurface = false;
}@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
/**
- A valid barcode has been found, so give an indication of success and show
- the results.
* - @param rawResult The contents of the barcode.
- @param bundle The extras
*/
public void handleDecode(Result rawResult, Bundle bundle) {
inactivityTimer.onActivity();
beepManager.playBeepSoundAndVibrate();
/*
這裏是掃描成功之後返回數據給界面,需要返回的數據在這裏添加
*/
Intent resultIntent = new Intent();
bundle.putInt(“width”, mCropRect.width()); //返回生成二維碼掃描框的寬
bundle.putInt(“height”, mCropRect.height());//返回生成二維碼掃描框的高
bundle.putString(“result”, rawResult.getText());//返回二維碼的內容
resultIntent.putExtras(bundle);
this.setResult(RESULT_OK, resultIntent);
CaptureActivity.this.finish();
}
private void initCamera(SurfaceHolder surfaceHolder) {
if (surfaceHolder == null) {
throw new IllegalStateException(“No SurfaceHolder provided”);
}
if (cameraManager.isOpen()) {
Log.w(TAG, “initCamera() while already open – late SurfaceView callback?”);
return;
}
try {
cameraManager.openDriver(surfaceHolder);
// Creating the handler starts the preview, which can also throw a
// RuntimeException.
if (handler == null) {
handler = new CaptureActivityHandler(this, cameraManager, DecodeThread.ALL_MODE);
}initCrop(); } catch (IOException ioe) { Log.w(TAG, ioe); displayFrameworkBugMessageAndExit(); } catch (RuntimeException e) { // Barcode Scanner has seen crashes in the wild of this variety: // java.?lang.?RuntimeException: Fail to connect to camera service Log.w(TAG, "Unexpected error initializing camera", e); displayFrameworkBugMessageAndExit(); }
}
private void displayFrameworkBugMessageAndExit() {
// camera error
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.app_name));
builder.setMessage(“Camera error”);
builder.setPositiveButton(“OK”, new DialogInterface.OnClickListener() {@Override public void onClick(DialogInterface dialog, int which) { finish(); } }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { finish(); } }); builder.show();
}
public void restartPreviewAfterDelay(long delayMS) {
if (handler != null) {
handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
}
}public Rect getCropRect() {
return mCropRect;
}/**
初始化截取的矩形區域
*/
private void initCrop() {
int cameraWidth = cameraManager.getCameraResolution().y;
int cameraHeight = cameraManager.getCameraResolution().x;/* 獲取佈局中掃描框的位置信息 /
int[] location = new int[2];
scanCropView.getLocationInWindow(location);int cropLeft = location[0];
int cropTop = location[1] - getStatusBarHeight();int cropWidth = scanCropView.getWidth();
int cropHeight = scanCropView.getHeight();/* 獲取佈局容器的寬高 /
int containerWidth = scanContainer.getWidth();
int containerHeight = scanContainer.getHeight();/* 計算最終截取的矩形的左上角頂點x座標 /
int x = cropLeft * cameraWidth / containerWidth;
/* 計算最終截取的矩形的左上角頂點y座標 /
int y = cropTop * cameraHeight / containerHeight;/* 計算最終截取的矩形的寬度 /
int width = cropWidth * cameraWidth / containerWidth;
/* 計算最終截取的矩形的高度 /
int height = cropHeight * cameraHeight / containerHeight;/* 生成最終的截取的矩形 /
mCropRect = new Rect(x, y, width + x, height + y);
}
private int getStatusBarHeight() {
try {
Class <> c = Class.forName(“com.android.internal.R$dimen”);//class<>裏面爲?
Object obj = c.newInstance();
Field field = c.getField(“status_bar_height”);
int x = Integer.parseInt(field.get(obj).toString());
return getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}
下面是二維碼生成工具類:
/**- 二維碼生成工具類
*/
public class EncodingUtils {
- 二維碼生成工具類
/**
- 創建二維碼
* - @param content content
- @param widthPix widthPix
- @param heightPix heightPix
- @param logoBm logoBm
- @return 二維碼
*/
public static Bitmap createQRCode(String content, int widthPix, int heightPix, Bitmap logoBm) {
try {
if (content == null || “”.equals(content)) {
return null;
}
// 配置參數
Map<> hints = new HashMap<>();//Map<>括號裏應該是EncodeHintType, Object不知道爲什麼csdn裏面這樣直接這樣寫會造成下面的內容全部不顯示
hints.put(EncodeHintType.CHARACTER_SET, “utf-8”);
// 容錯級別
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 圖像數據轉換,使用了矩陣轉換
BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix,
heightPix, hints);
int[] pixels = new int[widthPix * heightPix];
// 下面這裏按照二維碼的算法,逐個生成二維碼的圖片,
// 兩個for循環是圖片橫列掃描的結果
for (int y = 0; y < heightPix; y++) {
for (int x = 0; x < widthPix; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * widthPix + x] = 0xff000000;
} else {
pixels[y * widthPix + x] = 0xffffffff;
}
}
}
// 生成二維碼圖片的格式,使用ARGB_8888
Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix);
if (logoBm != null) {
bitmap = addLogo(bitmap, logoBm);
}
//必須使用compress方法將bitmap保存到文件中再進行讀取。直接返回的bitmap是沒有任何壓縮的,內存消耗巨大!
return bitmap;
} catch (WriterException e) {
e.printStackTrace();
}
return null;
}
/**
- 在二維碼中間添加Logo圖案
*/
private static Bitmap addLogo(Bitmap src, Bitmap logo) {
if (src == null) {
return null;
}
if (logo == null) {
return src;
}
//獲取圖片的寬高
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int logoWidth = logo.getWidth();
int logoHeight = logo.getHeight();
if (srcWidth == 0 || srcHeight == 0) {
return null;
}
if (logoWidth == 0 || logoHeight == 0) {
return src;
}
//logo大小爲二維碼整體大小的1/5
float scaleFactor = srcWidth * 1.0f / 5 / logoWidth;
Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
try {
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(src, 0, 0, null);
canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);
canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
} catch (Exception e) {
bitmap = null;
e.getStackTrace();
}
return bitmap;
}
}
這些類都是Zxing裏面的,自己可以根據需要去封裝。
封裝好了類之後其實我們的調用就很簡單了只需要寫一個Activity。
public class MainActivity extends AppCompatActivity {
@BindView(R.id.btn_camer)
Button btnCamer;
@BindView(R.id.tv_result)
TextView tvResult;
@BindView(R.id.et_qr_string)
EditText etQrString;
@BindView(R.id.btn_creat)
Button btnCreat;
@BindView(R.id.if_logo)
CheckBox ifLogo;
@BindView(R.id.iamge_show)
ImageView iamgeShow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
@OnClick({R.id.btn_camer, R.id.btn_creat, R.id.if_logo, R.id.iamge_show})
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_camer:
startActivityForResult(new Intent(MainActivity.this, CaptureActivity.class),0);//啓動掃描界面
break;
case R.id.btn_creat:
String str = etQrString.getText().toString();
if (str.equals("")) {
Toast.makeText(MainActivity.this, "不能爲空", Toast.LENGTH_SHORT).show();
} else {
// 位圖
try {
/**
* 參數:1.文本 2 3.二維碼的寬高 4.二維碼中間的那個logo
*/
Bitmap bitma = BitmapFactory.decodeResource(getResources(), R.drawable.zaizai);
Bitmap bitmap = EncodingUtils.createQRCode(str, 700, 700,bitma);
// 設置圖片
iamgeShow.setImageBitmap(bitmap);
Toast.makeText(this,"55555"+str,Toast.LENGTH_SHORT).show();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Toast.makeText(this,"55555",Toast.LENGTH_SHORT).show();
break;
case R.id.if_logo:
break;
case R.id.iamge_show:
break;
}
}
/*
掃描成功之後返回二維碼的信息在這裏接收處理
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
String result = data.getExtras().getString("result");
Toast.makeText(this,result+"1",Toast.LENGTH_SHORT).show();
tvResult.setText(result);
}
}
}
二維碼生成和掃描就這麼寫完了,但是在運行的時候竟然報控件空指針錯誤,就是說我的控件都是沒有生成找不到的在運行的時候,但是我明明用了ButterKnife也添加進去了還可以自動生成,但是註解運行的時候就是沒成功。後來找到了資料,原來在ButterKnife8.0以後引用發生了改變。現在必需多做幾道程序下面請看圖:
先把官網地址貼出來:http://jakewharton.github.io/butterknife/
github:https://github.com/JakeWharton/butterknife
接下來我們打開第一個gradle
添加classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’
第二步打開第二個gradle
apply plugin: ‘com.neenbedankt.android-apt’
compile ‘com.jakewharton:butterknife:8.4.0’
apt ‘com.jakewharton:butterknife-compiler:8.4.0’
最後注意添加的版本是不是一致,兩個gradle中Butter Knife版本必須一致。最後重新 clean project就完成了。
參考:http://www.cnblogs.com/zzw1994/p/5197758.html
將drawable下的圖片轉換成bitmap
1、 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xxx);
2、Resources r = this.getContext().getResources();
Inputstream is = r.openRawResource(R.drawable.xxx);
BitmapDrawable bmpDraw = new BitmapDrawable(is);
Bitmap bmp = bmpDraw.getBitmap();
3、Resources r = this.getContext().getResources();
Bitmap bmp=BitmapFactory.decodeResource(r, R.drawable.icon);
Bitmap bmp = Bitmap.createBitmap( 300, 300, Config.ARGB_8888 );
將drawable下的圖片轉換成Drawable
Resources resources = mContext.getResources();
Drawable drawable = resources.getDrawable(R.drawable.a);
imageview.setBackground(drawable);