Commit b0d40d64 authored by cyqresig's avatar cyqresig

finished first version

parent bf823673
*.[aod]
*.DS_Store
.DS_Store
*Thumbs.db
*.iml
.gradle
.idea
node_modules
npm-debug.log
/android/build
/ios/**/*xcuserdata*
/ios/**/*xcshareddata*
\ No newline at end of file
*.[aod]
*.DS_Store
.DS_Store
*Thumbs.db
*.iml
.gradle
.idea
node_modules
npm-debug.log
/android/build
/ios/**/*xcuserdata*
/ios/**/*xcshareddata*
\ No newline at end of file
import React, {
PropTypes,
Component,
} from 'react'
import {
View,
requireNativeComponent,
NativeModules,
AppState,
Platform,
} from 'react-native'
const BarcodeManager = Platform.OS == 'ios' ? NativeModules.Barcode : NativeModules.CaptureModule;
export default class Barcode extends Component {
static defaultProps = {
barCodeTypes: Object.values(BarcodeManager.barCodeTypes),
scannerRectWidth: 255,
scannerRectHeight: 255,
scannerRectTop: 0,
scannerRectLeft: 0,
scannerLineInterval: 3000,
scannerRectCornerColor: `#09BB0D`,
}
static propTypes = {
...View.propTypes,
onBarCodeRead: PropTypes.func.isRequired,
barCodeTypes: PropTypes.array,
scannerRectWidth: PropTypes.number,
scannerRectHeight: PropTypes.number,
scannerRectTop: PropTypes.number,
scannerRectLeft: PropTypes.number,
scannerLineInterval: PropTypes.number,
scannerRectCornerColor: PropTypes.string,
}
render() {
return (
<NativeBarCode
{...this.props}
/>
)
}
componentDidMount() {
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
startScan() {
BarcodeManager.startSession()
}
stopScan() {
BarcodeManager.stopSession()
}
_handleAppStateChange = (currentAppState) => {
if(currentAppState !== 'active' ) {
this.stopScan()
}
else {
this.startScan()
}
}
}
const NativeBarCode = requireNativeComponent(Platform.OS == 'ios' ? 'RCTBarcode' : 'CaptureView', Barcode)
# react-native-smart-barcode
\ No newline at end of file
# react-native-smart-barcode
A smart barcode scanner component for React Native app.
The library uses [https://github.com/zxing/zxing][1] to decode the barcodes for android.
[0]: https://github.com/cyqresig/ReactNativeComponentDemos
[1]: https://github.com/zxing/zxing
\ No newline at end of file
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion "24.0.0"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.facebook.react:react-native:+'
compile 'com.google.zxing:core:3.2.1'
}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/cyqresig/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.reactnativecomponent.barcode">
</manifest>
package com.reactnativecomponent.barcode;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.zxing.BarcodeFormat;
public class QRCodeResultEvent extends Event<QRCodeResultEvent> {
String result;
BarcodeFormat format;
public QRCodeResultEvent(int viewTag, long timestampMs,String result,BarcodeFormat format) {
// super(viewTag, timestampMs);
super(viewTag);
this.result=result;
this.format=format;
}
@Override
public String getEventName(){
return "QRCodeResult";
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData());
}
private WritableMap serializeEventData() {
WritableMap eventData = Arguments.createMap();
WritableMap data = Arguments.createMap();
data.putString("code", getResult());
data.putString("type",format.toString());
// Log.i("Test","code="+getResult());
eventData.putMap("data",data);
return eventData;
}
public String getResult() {
return result;
}
public BarcodeFormat getFormat() {
return format;
}
}
package com.reactnativecomponent.barcode;
import android.app.Activity;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.util.Log;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.SystemClock;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.google.zxing.BarcodeFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
public class RCTCaptureManager extends ViewGroupManager<CaptureView> {
private static final String REACT_CLASS = "CaptureView";//要与类名一致
public static final int CHANGE_SHOW = 0;//用来标记方法的下标
Activity activity;
CaptureView cap;
private float density;
public RCTCaptureManager(Activity activity) {
this.activity = activity;
density = activity.getResources().getDisplayMetrics().density;
}
@Override
public String getName() {
return REACT_CLASS;
}
@Override
public CaptureView createViewInstance(ThemedReactContext context) {
cap = new CaptureView(activity, context);
// ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//
// cap.setLayoutParams(params);
return cap;
}
@ReactProp(name = "barCodeTypes")
public void setbarCodeTypes(CaptureView view, ReadableArray barCodeTypes) {
if (barCodeTypes == null) {
return;
}
List<String> result = new ArrayList<String>(barCodeTypes.size());
for (int i = 0; i < barCodeTypes.size(); i++) {
result.add(barCodeTypes.getString(i));
}
view.setDecodeFormats(result);
}
@ReactProp(name = "scannerRectLeft", defaultInt = 0)
public void setCX(CaptureView view, int cX) {
view.setcX((int) (cX* density + 0.5f));
}
@ReactProp(name = "scannerRectTop", defaultInt = 0)
public void setCY(CaptureView view, int cY) {
view.setcY((int)(cY* density + 0.5f));
}
@ReactProp(name = "scannerRectWidth", defaultInt = 255)
public void setMAX_FRAME_WIDTH(CaptureView view, int FRAME_WIDTH) {
view.setMAX_FRAME_WIDTH((int) (FRAME_WIDTH * density + 0.5f));
}
@ReactProp(name = "scannerRectHeight", defaultInt = 255)
public void setMAX_FRAME_HEIGHT(CaptureView view, int FRAME_HEIGHT) {
view.setMAX_FRAME_HEIGHT((int) (FRAME_HEIGHT * density + 0.5f));
}
/* @ReactProp(name = "text")
public void setText(CaptureView view, String text) {
view.setText(text);
}*/
/* @ReactProp(name = "scannerRectCornerWidth", defaultInt = 4)
public void setCORNER_WIDTH(CaptureView view, int CORNER_WIDTH) {
if(CORNER_WIDTH<4){
CORNER_WIDTH=4;
}
view.setCORNER_WIDTH(CORNER_WIDTH);
}*/
/* @ReactProp(name = "scannerLineWidth", defaultInt = 3)
public void setMIDDLE_LINE_WIDTH(CaptureView view, int MIDDLE_LINE_WIDTH) {
if(MIDDLE_LINE_WIDTH<3){
MIDDLE_LINE_WIDTH=3;
}
view.setMIDDLE_LINE_WIDTH(MIDDLE_LINE_WIDTH);
}*/
//扫描线移动一圈时间
@ReactProp(name = "scannerLineInterval", defaultInt = 1000)
public void setTime(CaptureView view, int time) {
view.setScanTime(time);
}
/* //扫描框尺寸动画持续时间
@ReactProp(name = "changeTime", defaultInt = 1000)
public void setChangeTime(CaptureView view, int time) {
view.setChangeTime(time);
}
//camera聚集时间
@ReactProp(name = "focusTime", defaultInt = 1000)
public void setfocusTime(CaptureView view, int time) {
view.setFocusTime(time);
}
@ReactProp(name = "autoStart", defaultBoolean = true)
public void setAutoStart(CaptureView view, boolean start) {
view.setAutoStart(start);
}*/
@ReactProp(name = "scannerRectCornerColor")
public void setCORNER_COLOR(CaptureView view, String color) {
if (color != null && !color.isEmpty()) {
view.setCORNER_COLOR(Color.parseColor(color));//转换成16进制
}
}
/* //扫码成功提示音
@ReactProp(name = "playBeep",defaultBoolean = true)
public void setPlayBeep(CaptureView view, boolean isBeep) {
view.setPlayBeep(isBeep);
}
*/
@Override
public
@Nullable
Map<String, Integer> getCommandsMap() {
return MapBuilder.of(
"change",
CHANGE_SHOW);//js处发送的方法名字
}
@Override
public void receiveCommand(CaptureView root, int commandId, @Nullable ReadableArray config) {
// super.receiveCommand(root, commandId, config);
if (commandId == CHANGE_SHOW) {
this.changeWidthHeight(config.getMap(0));
}
}
@ReactMethod
public void changeWidthHeight(final ReadableMap config) {
// Log.i("Test", "changeWidthHeight");
if (cap != null) {
activity.runOnUiThread(new Runnable() {
public void run() {
int width = config.getInt("FRAME_WIDTH");
int height = config.getInt("FRAME_HEIGHT");
cap.setCHANGE_WIDTH((int)(width* density + 0.5f), (int)(height* density + 0.5f));
}
});
}
}
@Override
protected void addEventEmitters(
final ThemedReactContext reactContext,
final CaptureView view) {
view.setOnEvChangeListener(
new CaptureView.OnEvChangeListener() {
@Override
public void getQRCodeResult(String result,BarcodeFormat format) {
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher()
.dispatchEvent(new QRCodeResultEvent(view.getId(), SystemClock.nanoTime(), result,format));
}
});
}
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.<String, Object>builder()
.put("QRCodeResult", MapBuilder.of("registrationName", "onBarCodeRead"))//registrationName 后的名字,RN中方法也要是这个名字否则不执行
.build();
}
/*
@ReactProp(name = "aspect")
public void setAspect(CaptureView view, int aspect) {
view.setAspect(aspect);
}
@ReactProp(name = "captureMode")
public void setCaptureMode(RCTCameraView view, int captureMode) {
// TODO - implement video mode
}
@ReactProp(name = "captureTarget")
public void setCaptureTarget(RCTCameraView view, int captureTarget) {
// No reason to handle this props value here since it's passed again to the RCTCameraModule capture method
}
@ReactProp(name = "type")
public void setType(RCTCameraView view, int type) {
view.setCameraType(type);
}
*/
}
\ No newline at end of file
package com.reactnativecomponent.barcode;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.widget.Toast;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.google.zxing.BarcodeFormat;
import com.reactnativecomponent.barcode.decoding.DecodeUtil;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class RCTCaptureModule extends ReactContextBaseJavaModule {
private ReactApplicationContext mContext;
RCTCaptureManager captureManager;
public RCTCaptureModule(ReactApplicationContext reactContext, RCTCaptureManager captureManager) {
super(reactContext);
mContext = reactContext;
this.captureManager = captureManager;
}
@Override
public String getName() {
return "CaptureModule";
}
// public void sendMsgToRn(String msg) {
// //将消息msg发送给RN侧
// mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("AndroidToRNMessage", msg);
//
// }
@Nullable
@Override
public Map<String, Object> getConstants() {
return Collections.unmodifiableMap(new HashMap<String, Object>() {
{
put("barCodeTypes", getBarCodeTypes());
}
private Map<String, Object> getBarCodeTypes() {
return Collections.unmodifiableMap(new HashMap<String, Object>() {
{
put("upce", BarcodeFormat.UPC_E.toString());
put("code39", BarcodeFormat.CODE_39.toString());
// put("code39mod43",BarcodeFormat. );
put("ean13",BarcodeFormat.EAN_13.toString() );
put("ean8",BarcodeFormat.EAN_8.toString() );
put("code93", BarcodeFormat.CODE_93.toString());
put("code128", BarcodeFormat.CODE_128.toString());
put("pdf417",BarcodeFormat.PDF_417.toString() );
put("qr",BarcodeFormat.QR_CODE.toString() );
put("aztec", BarcodeFormat.AZTEC.toString());
// put("interleaved2of5", BarcodeFormat.);
put("itf14",BarcodeFormat.ITF.toString());
put("datamatrix", BarcodeFormat.DATA_MATRIX.toString());
}
});
}
});
}
@ReactMethod
public void startSession() {
if (captureManager.cap != null) {
getCurrentActivity().runOnUiThread(new Runnable() {
public void run() {
captureManager.cap.startQR();
// captureManager.cap.startScan();
// Toast.makeText(getCurrentActivity(), "startScan", Toast.LENGTH_SHORT).show();
}
});
}
}
@ReactMethod
public void stopSession() {
if (captureManager.cap != null) {
getCurrentActivity().runOnUiThread(new Runnable() {
public void run() {
// captureManager.cap.stopQR();
captureManager.cap.stopScan();
// Toast.makeText(getCurrentActivity(), "stopScan", Toast.LENGTH_SHORT).show();
}
});
}
}
@ReactMethod
public void stopFlash() {
if (captureManager.cap != null) {
getCurrentActivity().runOnUiThread(new Runnable() {
public void run() {
captureManager.cap.CloseFlash();
// Toast.makeText(getCurrentActivity(), "stopFlash", Toast.LENGTH_SHORT).show();
}
});
}
}
@ReactMethod
public void startFlash() {
if (captureManager.cap != null) {
getCurrentActivity().runOnUiThread(new Runnable() {
public void run() {
captureManager.cap.OpenFlash();
// Toast.makeText(getCurrentActivity(), "startFlash", Toast.LENGTH_SHORT).show();
}
});
}
}
@ReactMethod
public void DecodeFromPath(final String path,
final Callback errorCallback,
final Callback successCallback) {
new Thread(new Runnable() {
public void run() {
try {
String s = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/" + "IMG_20161011_170552.jpg";
//不加这个分号则不能自动添加代码
String ResultStr = DecodeUtil.getStringFromQRCode(s);
successCallback.invoke(ResultStr);
} catch (Exception e) {
e.printStackTrace();
errorCallback.invoke(e.getMessage());
}
}
}).start();
// Toast.makeText(getCurrentActivity(), "DecodeFromPath:"+path, Toast.LENGTH_SHORT).show();
}
/*
@ReactMethod
public void changeWidthHeight(final int width,final int height) {
if (captureManager.cap != null) {
activity.runOnUiThread(new Runnable() {
public void run() {
captureManager.cap.setCHANGE_WIDTH(width, height);
}
});
}
}*/
}
package com.reactnativecomponent.barcode;
import android.app.Activity;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class RCTCapturePackage implements ReactPackage {
Activity activity;
RCTCaptureModule mModuleInstance;
RCTCaptureManager captureManager;
// RCTLinearGradientViewManager linearGradientViewManager;
public RCTCapturePackage(Activity activity) {
this.activity = activity;
captureManager = new RCTCaptureManager(activity);
// linearGradientViewManager = new RCTLinearGradientViewManager(activity);
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) {
mModuleInstance = new RCTCaptureModule(reactApplicationContext,captureManager);
return Arrays.<NativeModule>asList(
mModuleInstance
);
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
//noinspection ArraysAsListWithZeroOrOneArgument
// return Arrays.<ViewManager>asList(captureManager,linearGradientViewManager);
return Arrays.<ViewManager>asList(captureManager);
}
}
package com.reactnativecomponent.barcode;
import android.app.Activity;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.ViewGroup;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.reactnativecomponent.barcode.view.LinearGradientView;
public class RCTLinearGradientViewManager extends SimpleViewManager<LinearGradientView>{
private static final String REACT_CLASS = "LinearGradientView";//要与类名一致
LinearGradientView linearGradientView;
private float density;
Activity activity;
public RCTLinearGradientViewManager(Activity activity) {
this.activity=activity;
density = activity.getResources().getDisplayMetrics().density;
}
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected LinearGradientView createViewInstance(ThemedReactContext reactContext) {
linearGradientView=new LinearGradientView(reactContext,activity);
return linearGradientView;
}
@ReactProp(name = "size" ,defaultInt = 1)
public void setSize(LinearGradientView view,int size) {
int num=(int)(size*density+0.5f);
if(num<3){
num=3;
}else if(num >10){
num=5;
}
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.height=num;
params.width =view.width;
view.setLayoutParams(params);
view.size=num;
}
@ReactProp(name = "width" ,defaultInt = 0)
public void setWidth(LinearGradientView view, int width) {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
if((int) (width * density + 0.5f)>1) {
params.width = (int) (width * density + 0.5f);
params.height=view.size;
}
view.width=(int)(width*density+0.5f);
view.setLayoutParams(params);
}
@ReactProp(name = "frameColor")
public void setFrameColor(LinearGradientView view, String color) {
if (color != null && !color.isEmpty()) {
view.setFrameColor(Color.parseColor(color));//转换成16进制
}
}
@Override
public void setBackgroundColor(LinearGradientView view, int backgroundColor) {
// super.setBackgroundColor(view, backgroundColor);
}
}
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.camera;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
final class AutoFocusCallback implements Camera.AutoFocusCallback {
private static final String TAG = AutoFocusCallback.class.getSimpleName();
public long AUTOFOCUS_INTERVAL_MS = 500L;//自动聚焦触发 毫秒数
// private static final long AUTOFOCUS_INTERVAL_MS = 1500L;
private Handler autoFocusHandler;
private int autoFocusMessage;
void setHandler(Handler autoFocusHandler, int autoFocusMessage) {
this.autoFocusHandler = autoFocusHandler;
this.autoFocusMessage = autoFocusMessage;
}
public void onAutoFocus(boolean success, Camera camera) {
if (autoFocusHandler != null) {
Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
// Simulate continuous autofocus by sending a focus request every
// AUTOFOCUS_INTERVAL_MS milliseconds.
//Log.d(TAG, "Got auto-focus callback; requesting another");
autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
autoFocusHandler = null;
} else {
// Log.d(TAG, "Got auto-focus callback, but no handler for it");
}
}
}
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.camera;
import android.os.IBinder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* This class is used to activate the weak light on some camera phones (not flash)
* in order to illuminate surfaces for scanning. There is no official way to do this,
* but, classes which allow access to this function still exist on some devices.
* This therefore proceeds through a great deal of reflection.
*
* See <a href="http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/">
* http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/</a> and
* <a href="http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java">
* http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java</a>.
* Thanks to Ryan Alford for pointing out the availability of this class.
*/
final class FlashlightManager {
private static final String TAG = FlashlightManager.class.getSimpleName();
private static final Object iHardwareService;
private static final Method setFlashEnabledMethod;
static {
iHardwareService = getHardwareService();
setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);
if (iHardwareService == null) {
// Log.v(TAG, "This device does supports control of a flashlight");
} else {
// Log.v(TAG, "This device does not support control of a flashlight");
}
}
private FlashlightManager() {
}
private static Object getHardwareService() {
Class<?> serviceManagerClass = maybeForName("android.os.ServiceManager");
if (serviceManagerClass == null) {
return null;
}
Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
if (getServiceMethod == null) {
return null;
}
Object hardwareService = invoke(getServiceMethod, null, "hardware");
if (hardwareService == null) {
return null;
}
Class<?> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
if (iHardwareServiceStubClass == null) {
return null;
}
Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", IBinder.class);
if (asInterfaceMethod == null) {
return null;
}
return invoke(asInterfaceMethod, null, hardwareService);
}
private static Method getSetFlashEnabledMethod(Object iHardwareService) {
if (iHardwareService == null) {
return null;
}
Class<?> proxyClass = iHardwareService.getClass();
return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class);
}
private static Class<?> maybeForName(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException cnfe) {
// OK
return null;
} catch (RuntimeException re) {
// Log.w(TAG, "Unexpected error while finding class " + name, re);
return null;
}
}
private static Method maybeGetMethod(Class<?> clazz, String name, Class<?>... argClasses) {
try {
return clazz.getMethod(name, argClasses);
} catch (NoSuchMethodException nsme) {
// OK
return null;
} catch (RuntimeException re) {
// Log.w(TAG, "Unexpected error while finding method " + name, re);
return null;
}
}
private static Object invoke(Method method, Object instance, Object... args) {
try {
return method.invoke(instance, args);
} catch (IllegalAccessException e) {
// Log.w(TAG, "Unexpected error while invoking " + method, e);
return null;
} catch (InvocationTargetException e) {
// Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
return null;
} catch (RuntimeException re) {
// Log.w(TAG, "Unexpected error while invoking " + method, re);
return null;
}
}
static void enableFlashlight() {
setFlashlight(true);
}
static void disableFlashlight() {
setFlashlight(false);
}
private static void setFlashlight(boolean active) {
if (iHardwareService != null) {
invoke(setFlashEnabledMethod, iHardwareService, active);
}
}
}
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.camera;
import android.graphics.Bitmap;
import android.util.Log;
import com.google.zxing.LuminanceSource;
/**
* This object extends LuminanceSource around an array of YUV data returned from the camera driver,
* with the option to crop to a rectangle within the full data. This can be used to exclude
* superfluous pixels around the perimeter and speed up decoding.
*
* It works for any pixel format where the Y channel is planar and appears first, including
* YCbCr_420_SP and YCbCr_422_SP.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class PlanarYUVLuminanceSource extends LuminanceSource {
private final byte[] yuvData;
private final int dataWidth;
private final int dataHeight;
private final int left;
private final int top;
public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,
int width, int height) {
super(width, height);
if (left + width > dataWidth || top + height > dataHeight) {
throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
}
this.yuvData = yuvData;
this.dataWidth = dataWidth;
this.dataHeight = dataHeight;
this.left = left;
this.top = top;
}
@Override
public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException("Requested row is outside the image: " + y);
}
int width = getWidth();
if (row == null || row.length < width) {
row = new byte[width];
}
int offset = (y + top) * dataWidth + left;
try {
System.arraycopy(yuvData, offset, row, 0, width);
} catch (ArrayIndexOutOfBoundsException e) {
// Log.e("Exception","ArrayIndexOutOfBoundsException:"+e);
e.printStackTrace();
}
return row;
}
@Override
public byte[] getMatrix() {
int width = getWidth();
int height = getHeight();
// If the caller asks for the entire underlying image, save the copy and give them the
// original data. The docs specifically warn that result.length must be ignored.
if (width == dataWidth && height == dataHeight) {
return yuvData;
}
int area = width * height;
byte[] matrix = new byte[area];
int inputOffset = top * dataWidth + left;
// If the width matches the full width of the underlying data, perform a single copy.
if (width == dataWidth) {
System.arraycopy(yuvData, inputOffset, matrix, 0, area);
return matrix;
}
// Otherwise copy one cropped row at a time.
byte[] yuv = yuvData;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
try {
System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);
} catch (ArrayIndexOutOfBoundsException e) {
// Log.e("Exception","ArrayIndexOutOfBoundsException:"+e);
e.printStackTrace();
}
inputOffset += dataWidth;
}
return matrix;
}
@Override
public boolean isCropSupported() {
return true;
}
public int getDataWidth() {
return dataWidth;
}
public int getDataHeight() {
return dataHeight;
}
public Bitmap renderCroppedGreyscaleBitmap() {
int width = getWidth();
int height = getHeight();
int[] pixels = new int[width * height];
byte[] yuv = yuvData;
int inputOffset = top * dataWidth + left;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
for (int x = 0; x < width; x++) {
int grey = 0;
try {
grey = yuv[inputOffset + x] & 0xff;
} catch (ArrayIndexOutOfBoundsException e) {
// Log.e("Exception","ArrayIndexOutOfBoundsException:"+e);
e.printStackTrace();
}
pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
}
inputOffset += dataWidth;
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.camera;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
final class PreviewCallback implements Camera.PreviewCallback {
private static final String TAG = PreviewCallback.class.getSimpleName();
private final CameraConfigurationManager configManager;
private final boolean useOneShotPreviewCallback;
private Handler previewHandler;
private int previewMessage;
PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {
this.configManager = configManager;
this.useOneShotPreviewCallback = useOneShotPreviewCallback;
}
void setHandler(Handler previewHandler, int previewMessage) {
this.previewHandler = previewHandler;
this.previewMessage = previewMessage;
}
public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
if (previewHandler != null) {
Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,
cameraResolution.y, data);
message.sendToTarget();
previewHandler = null;
} else {
// Log.d(TAG, "Got preview callback, but no handler for it");
}
}
}
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.decoding;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.reactnativecomponent.barcode.CaptureView;
import com.reactnativecomponent.barcode.R;
import com.reactnativecomponent.barcode.camera.CameraManager;
import com.reactnativecomponent.barcode.view.ViewfinderResultPointCallback;
import java.util.Vector;
/**
* This class handles all the messaging which comprises the state machine for capture.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class CaptureActivityHandler extends Handler {
private static final String TAG = CaptureActivityHandler.class.getSimpleName();
private final CaptureView captureView;
private final DecodeThread decodeThread;
private State state;
private enum State {
PREVIEW,
SUCCESS,
DONE
}
public CaptureActivityHandler(CaptureView captureView, Vector<BarcodeFormat> decodeFormats,
String characterSet) {
this.captureView = captureView;
decodeThread = new DecodeThread(captureView, decodeFormats, characterSet,
new ViewfinderResultPointCallback(captureView.getViewfinderView()));
decodeThread.start();
state = State.SUCCESS;
// Start ourselves capturing previews and decoding.
CameraManager.get().startPreview();
restartPreviewAndDecode();
}
@Override
public void handleMessage(Message message) {
if (message.what == R.id.auto_focus) {// case R.id.auto_focus:
//Log.d(TAG, "Got auto-focus message");
// When one auto focus pass finishes, start another. This is the closest thing to
// continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
if (state == State.PREVIEW) {
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
}
} else if (message.what == R.id.restart_preview) {// case R.id.restart_preview:
// Log.d(TAG, "Got restart preview message");
restartPreviewAndDecode();
} else if (message.what == R.id.decode_succeeded) {// case R.id.decode_succeeded:
// Log.d(TAG, "Got decode succeeded message");
state = State.SUCCESS;
Bundle bundle = message.getData();
/* Bitmap barcode = bundle == null ? null :
(Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);*/
captureView.handleDecode((Result) message.obj, null);
// case R.id.decode_failed:
} else if (message.what == R.id.decode_failed) {/**
*扫码失败继续执行线程
*/
// We're decoding as fast as possible, so when one decode fails, start another.
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
} else if (message.what == R.id.return_scan_result) {// Log.d(TAG, "Got return scan result message");
captureView.ShowResult((Intent) message.obj);
/* case R.id.launch_product_query:
Log.d(TAG, "Got product query message");
String url = (String) message.obj;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
activity.startActivity(intent);
break;*/
}
}
public void quitSynchronously() {
if (state != State.DONE) {
state = State.DONE;
CameraManager.get().stopPreview();
Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
quit.sendToTarget();
decodeThread.flag=false;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
decodeThread.interrupt();
try {
decodeThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
// continue
}
// Be absolutely sure we don't send any queued up messages
removeMessages(R.id.decode_succeeded);
removeMessages(R.id.decode_failed);
}
}
public void restartPreviewAndDecode() {
if (state == State.SUCCESS) {
state = State.PREVIEW;
decodeThread.flag=true;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
captureView.drawViewfinder();
}
}
}
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.decoding;
import android.content.Intent;
import android.net.Uri;
import com.google.zxing.BarcodeFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;
public class DecodeFormatManager {
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
static final Vector<BarcodeFormat> PRODUCT_FORMATS;
static final Vector<BarcodeFormat> ONE_D_FORMATS;
static final Vector<BarcodeFormat> QR_CODE_FORMATS;
static final Vector<BarcodeFormat> DATA_MATRIX_FORMATS;
static {
PRODUCT_FORMATS = new Vector<BarcodeFormat>(5);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_A);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);
PRODUCT_FORMATS.add(BarcodeFormat.RSS_14);
ONE_D_FORMATS = new Vector<BarcodeFormat>(PRODUCT_FORMATS.size() + 4);
ONE_D_FORMATS.addAll(PRODUCT_FORMATS);
ONE_D_FORMATS.add(BarcodeFormat.CODE_39);
ONE_D_FORMATS.add(BarcodeFormat.CODE_93);
ONE_D_FORMATS.add(BarcodeFormat.CODE_128);
ONE_D_FORMATS.add(BarcodeFormat.ITF);
QR_CODE_FORMATS = new Vector<BarcodeFormat>(1);
QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
DATA_MATRIX_FORMATS = new Vector<BarcodeFormat>(1);
DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
}
private DecodeFormatManager() {}
static Vector<BarcodeFormat> parseDecodeFormats(Intent intent) {
List<String> scanFormats = null;
String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS);
if (scanFormatsString != null) {
scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString));
}
return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE));
}
static Vector<BarcodeFormat> parseDecodeFormats(Uri inputUri) {
List<String> formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS);
if (formats != null && formats.size() == 1 && formats.get(0) != null){
formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0)));
}
return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE));
}
private static Vector<BarcodeFormat> parseDecodeFormats(Iterable<String> scanFormats,
String decodeMode) {
if (scanFormats != null) {
Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();
try {
for (String format : scanFormats) {
formats.add(BarcodeFormat.valueOf(format));
}
return formats;
} catch (IllegalArgumentException iae) {
// ignore it then
}
}
if (decodeMode != null) {
if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) {
return PRODUCT_FORMATS;
}
if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) {
return QR_CODE_FORMATS;
}
if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) {
return DATA_MATRIX_FORMATS;
}
if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) {
return ONE_D_FORMATS;
}
}
return null;
}
}
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.decoding;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.reactnativecomponent.barcode.CaptureView;
import com.reactnativecomponent.barcode.R;
import com.reactnativecomponent.barcode.camera.CameraManager;
import com.reactnativecomponent.barcode.camera.PlanarYUVLuminanceSource;
import java.util.Hashtable;
final class
DecodeHandler extends Handler {
// private static final String TAG = DecodeHandler.class.getSimpleName();
private static final String TAG ="Test";
private final CaptureView captureView;
private final MultiFormatReader multiFormatReader;
DecodeHandler(CaptureView captureView, Hashtable<DecodeHintType, Object> hints) {
multiFormatReader = new MultiFormatReader();
multiFormatReader.setHints(hints);
this.captureView = captureView;
}
@Override
public void handleMessage(Message message) {
int id=message.what;
if(id== R.id.decode) {
if(captureView.decodeFlag) {
decode((byte[]) message.obj, message.arg1, message.arg2);
}
}else if(id==R.id.quit) {
// Log.i(TAG, "decode quit");
Looper.myLooper().quit();
}
}
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
* reuse the same reader objects from one decode to the next.
*
* @param data The YUV preview frame.
* @param width The width of the preview frame.
* @param height The height of the preview frame.
*/
private void decode(byte[] data, int width, int height) {
// Log.v("DecodeHandler", data.length + "");
// {
// StringBuilder tmp;
// // if the data width is 480
// {
// int x = 40;
// tmp = new StringBuilder();
// for (int y = 0; y < height; y += 20)
// tmp.append(Integer.toHexString(data[y * width + x]) + "_");
// Log.v("DecodeHandler", tmp.toString());
// }
// // if the data width is 320
// {
// int x = 40;
// tmp = new StringBuilder();
// for (int y = 0; y < width; y += 20)
// tmp.append(Integer.toHexString(data[y * height + x]) + "_");
// Log.v("DecodeHandler", tmp.toString());
// }
// }
// rotate the data 90 degree clockwise.
// note that on a HTC G2, data length is 230400, but 480*320=153600,
// which means u and v channels are not touched.
// from the rotated data you will get a wrong image, whatever, only Y
// channel is used.
// check PlanarYUVLuminanceSource for more.
// it says: "It works for any pixel format where
// the Y channel is planar and appears first, including
// YCbCr_420_SP and YCbCr_422_SP."
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
rotatedData[x * height + height - y - 1] = data[x + y * width];
}
long start = System.currentTimeMillis();
Result rawResult = null;
// PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, width, height);
// PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, height, width);
// switch width and height
// Log.i("Test","DecodeHandler_height:"+height+",width:"+width);
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, height, width);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);
} catch (ReaderException re) {
// continue
} finally {
multiFormatReader.reset();
}
if (rawResult != null) {
long end = System.currentTimeMillis();
// Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
Message message = Message.obtain(captureView.getHandler(), R.id.decode_succeeded, rawResult);
Bundle bundle = new Bundle();
bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
message.setData(bundle);
//Log.d(TAG, "Sending decode succeeded message...");
message.sendToTarget();
} else {
Message message = Message.obtain(captureView.getHandler(), R.id.decode_failed);
message.sendToTarget();
}
}
}
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.decoding;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.ResultPointCallback;
import com.reactnativecomponent.barcode.CaptureView;
import com.reactnativecomponent.barcode.R;
import java.util.Hashtable;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
/**
* This thread does all the heavy lifting of decoding the images.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
final class DecodeThread extends Thread {
public static final String BARCODE_BITMAP = "barcode_bitmap";
private final CaptureView captureView;
private final Hashtable<DecodeHintType, Object> hints;
private DecodeHandler handler;
private final CountDownLatch handlerInitLatch;//到计数的锁
public boolean flag=true;
DecodeThread(CaptureView captureView,
Vector<BarcodeFormat> decodeFormats,
String characterSet,
ResultPointCallback resultPointCallback) {
// Log.i("Test", "DecodeThread create");
this.captureView = captureView;
handlerInitLatch = new CountDownLatch(1);//从1开始到计数
hints = new Hashtable<DecodeHintType, Object>(3);
// // The prefs can't change while the thread is running, so pick them up once here.
// if (decodeFormats == null || decodeFormats.isEmpty()) {
// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
// decodeFormats = new Vector<BarcodeFormat>();
// if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true)) {
// decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
// }
// if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true)) {
// decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
// }
// if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_DATA_MATRIX, true)) {
// decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
// }
// }
if (decodeFormats == null || decodeFormats.isEmpty()) {
decodeFormats = new Vector<BarcodeFormat>();
decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
}
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
if (characterSet != null) {
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
}
hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
}
Handler getHandler() {
try {
handlerInitLatch.await();//阻塞先等handler被初始化了才能返回结果。改计数锁即等countdown-->0。
} catch (InterruptedException ie) {
// continue?
}
return handler;
}
@Override
public void run() {
Looper.prepare();
handler = new DecodeHandler(captureView, hints);
handlerInitLatch.countDown();//启动到计数,countdown-1 变成0;
// Log.i("Test","The worker thread id = " + Thread.currentThread().getId()); //判断线程ID
Looper.loop();
}
}
package com.reactnativecomponent.barcode.decoding;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import java.lang.ref.WeakReference;
import java.util.Hashtable;
public class DecodeUtil {
public static Bitmap convertToBitmap(String path) {
BitmapFactory.Options opts = new BitmapFactory.Options();
// 设置为ture只获取图片大小
opts.inJustDecodeBounds = true;
opts.inPreferredConfig = Bitmap.Config.RGB_565;
// 返回为空
BitmapFactory.decodeFile(path, opts);
int width = opts.outWidth;
int height = opts.outHeight;
/* float scaleWidth = 0.f, scaleHeight = 0.f;
if (width > w || height > h){
// 缩放
scaleWidth = ((float) width) / w;
scaleHeight = ((float) height) / h;
}*/
opts.inJustDecodeBounds = false;
// float scale = Math.max(scaleWidth, scaleHeight);
float scale = 1.5f;
opts.inSampleSize = (int)scale;
WeakReference<Bitmap> weak = new WeakReference<Bitmap>(BitmapFactory.decodeFile(path, opts));
return Bitmap.createScaledBitmap(weak.get(), (int)(width/scale), (int)(height/scale), true);
}
public static String getStringFromQRCode(String path) {
String httpString = null;
Bitmap bmp = convertToBitmap(path);
byte[] data = getYUV420sp(bmp.getWidth(), bmp.getHeight(), bmp);
// 处理
try {
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
// hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,
bmp.getWidth(),
bmp.getHeight(),
0, 0,
bmp.getWidth(),
bmp.getHeight(),
false);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader2= new QRCodeReader();
Result result = reader2.decode(bitmap1, hints);
httpString = result.getText();
} catch (Exception e) {
e.printStackTrace();
}
bmp.recycle();
bmp = null;
return httpString;
}
/**
* YUV420sp
*
* @param inputWidth
* @param inputHeight
* @param scaled
* @return
*/
public static byte[] getYUV420sp(int inputWidth, int inputHeight,
Bitmap scaled) {
int[] argb = new int[inputWidth * inputHeight];
scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);
byte[] yuv = new byte[inputWidth * inputHeight * 3 / 2];
encodeYUV420SP(yuv, argb, inputWidth, inputHeight);
scaled.recycle();
return yuv;
}
/**
* RGB转YUV420sp
*
* @param yuv420sp
* inputWidth * inputHeight * 3 / 2
* @param argb
* inputWidth * inputHeight
* @param width
* @param height
*/
private static void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width,
int height) {
// 帧图片的像素大小
final int frameSize = width * height;
// ---YUV数据---
int Y, U, V;
// Y的index从0开始
int yIndex = 0;
// UV的index从frameSize开始
int uvIndex = frameSize;
// ---颜色数据---
// int a, R, G, B;
int R, G, B;
//
int argbIndex = 0;
//
// ---循环所有像素点,RGB转YUV---
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
// a is not used obviously
// a = (argb[argbIndex] & 0xff000000) >> 24;
R = (argb[argbIndex] & 0xff0000) >> 16;
G = (argb[argbIndex] & 0xff00) >> 8;
B = (argb[argbIndex] & 0xff);
//
argbIndex++;
// well known RGB to YUV algorithm
Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
//
Y = Math.max(0, Math.min(Y, 255));
U = Math.max(0, Math.min(U, 255));
V = Math.max(0, Math.min(V, 255));
// NV21 has a plane of Y and interleaved planes of VU each
// sampled by a factor of 2
// meaning for every 4 Y pixels there are 1 V and 1 U. Note the
// sampling is every other
// pixel AND every other scanline.
// ---Y---
yuv420sp[yIndex++] = (byte) Y;
// ---UV---
if ((j % 2 == 0) && (i % 2 == 0)) {
//
yuv420sp[uvIndex++] = (byte) V;
//
yuv420sp[uvIndex++] = (byte) U;
}
}
}
}
}
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.decoding;
import android.app.Activity;
import android.content.DialogInterface;
/**
* Simple listener used to exit the app in a few cases.
*
* @author Sean Owen
*/
public final class FinishListener
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {
private final Activity activityToFinish;
public FinishListener(Activity activityToFinish) {
this.activityToFinish = activityToFinish;
}
public void onCancel(DialogInterface dialogInterface) {
run();
}
public void onClick(DialogInterface dialogInterface, int i) {
run();
}
public void run() {
activityToFinish.finish();
}
}
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.decoding;
import android.app.Activity;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* Finishes an activity after a period of inactivity.
*
*/
public final class InactivityTimer {
private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
private final ScheduledExecutorService inactivityTimer =
Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
private final Activity activity;
private ScheduledFuture<?> inactivityFuture = null;
public InactivityTimer(Activity activity) {
this.activity = activity;
onActivity();
}
public void onActivity() {
cancel();
inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
INACTIVITY_DELAY_SECONDS,
TimeUnit.SECONDS);
}
private void cancel() {
if (inactivityFuture != null) {
inactivityFuture.cancel(true);
inactivityFuture = null;
}
}
public void shutdown() {
cancel();
inactivityTimer.shutdown();
}
private static final class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
return thread;
}
}
}
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.decoding;
/**
* This class provides the constants to use when sending an Intent to Barcode Scanner.
* These strings are effectively API and cannot be changed.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class Intents {
private Intents() {
}
public static final class Scan {
/**
* Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
* the results.
*/
public static final String ACTION = "com.google.zxing.client.android.SCAN";
/**
* By default, sending Scan.ACTION will decode all barcodes that we understand. However it
* may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with
* one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}).
* Optional.
*
* Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}.
* It is overridden by that setting.
*/
public static final String MODE = "SCAN_MODE";
/**
* Comma-separated list of formats to scan for. The values must match the names of
* {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}.
* Example: "EAN_13,EAN_8,QR_CODE"
*
* This overrides {@link #MODE}.
*/
public static final String SCAN_FORMATS = "SCAN_FORMATS";
/**
* @see com.google.zxing.DecodeHintType#CHARACTER_SET
*/
public static final String CHARACTER_SET = "CHARACTER_SET";
/**
* Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get
* prices, reviews, etc. for products.
*/
public static final String PRODUCT_MODE = "PRODUCT_MODE";
/**
* Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).
*/
public static final String ONE_D_MODE = "ONE_D_MODE";
/**
* Decode only QR codes.
*/
public static final String QR_CODE_MODE = "QR_CODE_MODE";
/**
* Decode only Data Matrix codes.
*/
public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE";
/**
* If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which
* requested the scan via startSubActivity(). The barcodes contents can be retrieved with
* intent.getStringExtra(RESULT). If the user presses Back, the result code will be
* RESULT_CANCELED.
*/
public static final String RESULT = "SCAN_RESULT";
/**
* Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
* See Contents.Format for possible values.
*/
public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
/**
* Setting this to false will not save scanned codes in the history.
*/
public static final String SAVE_HISTORY = "SAVE_HISTORY";
private Scan() {
}
}
public static final class Encode {
/**
* Send this intent to encode a piece of data as a QR code and display it full screen, so
* that another person can scan the barcode from your screen.
*/
public static final String ACTION = "com.google.zxing.client.android.ENCODE";
/**
* The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a
* Bundle, depending on the type and format specified. Non-QR Code formats should
* just use a String here. For QR Code, see Contents for details.
*/
public static final String DATA = "ENCODE_DATA";
/**
* The type of data being supplied if the format is QR Code. Use
* Intent.putExtra(TYPE, type) with one of Contents.Type.
*/
public static final String TYPE = "ENCODE_TYPE";
/**
* The barcode format to be displayed. If this isn't specified or is blank,
* it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where
* format is one of Contents.Format.
*/
public static final String FORMAT = "ENCODE_FORMAT";
private Encode() {
}
}
public static final class SearchBookContents {
/**
* Use Google Book Search to search the contents of the book provided.
*/
public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS";
/**
* The book to search, identified by ISBN number.
*/
public static final String ISBN = "ISBN";
/**
* An optional field which is the text to search for.
*/
public static final String QUERY = "QUERY";
private SearchBookContents() {
}
}
public static final class WifiConnect {
/**
* Internal intent used to trigger connection to a wi-fi network.
*/
public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String SSID = "SSID";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String TYPE = "TYPE";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String PASSWORD = "PASSWORD";
private WifiConnect() {
}
}
public static final class Share {
/**
* Give the user a choice of items to encode as a barcode, then render it as a QR Code and
* display onscreen for a friend to scan with their phone.
*/
public static final String ACTION = "com.google.zxing.client.android.SHARE";
private Share() {
}
}
}
package com.reactnativecomponent.barcode.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.GradientDrawable;
import android.view.View;
import android.view.ViewGroup;
public class LinearGradientView extends View {
// /* *//**
// * 中间滑动线的最顶端位置
// *//*
// private int slideTop;
//
// *//**
// * 中间那条线每次刷新移动的距离
// *//*
// private static int SPEEN_DISTANCE = 3;
//
// *//**
// * 中间滑动线的最底端位置
// *//*
// private int slideBottom;
//
// *//**
// * 四个蓝色边角对应的宽度
// *//*
// public int CORNER_WIDTH = 3;*/
/**
* 框架颜色
*/
public int frameColor=Color.GREEN;
/**
* 扫描线渐变色中间色
*/
public int frameBaseColor;
/**
* 线的厚度
*/
public int size;
/**
* 线的宽度
*/
public int width;
Activity activity;
// /**
// * 扫描框中的中间线的宽度
// */
// private static final int MIDDLE_LINE_WIDTH = 3;
// public int top,left,right;
// private Paint paintLine;
public LinearGradientView(Context context,Activity activity) {
super(context);
this.activity=activity;
// paintLine=new Paint();
}
public void setFrameColor(int frameColor) {
this.frameColor = frameColor;
this.frameBaseColor = reSetColor(frameColor);
//渐变色drawable
int[] mColors = new int[]{Color.TRANSPARENT, frameBaseColor, frameColor, frameColor, frameColor, frameColor, frameColor, frameBaseColor, Color.TRANSPARENT};
GradientDrawable drawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, mColors);
drawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
// drawable.setCornerRadius(15);
// drawable.setStroke(10,-1);
setBackground(drawable);
}
@Override
protected void onAttachedToWindow() {
ViewGroup.LayoutParams params= getLayoutParams();
if(size>1) {
params.height = size;
}
if(width>1){
params.width=width;
}
setLayoutParams(params);
super.onAttachedToWindow();
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final ViewGroup.LayoutParams params= getLayoutParams();
int height = getHeight();
if (height < 3) {
params.height = 3;
} else if (height > 10) {
params.height = 10;
}
activity.runOnUiThread(new Runnable() {
public void run() {
LinearGradientView.this.setLayoutParams(params);
}
});
super.onLayout(changed, left, top, right, bottom);
}
/* @Override
protected void onDraw(Canvas canvas) {
paintLine.setColor(frameColor);
slideTop += SPEEN_DISTANCE;
if (slideTop >= slideBottom) {
slideTop = top + CORNER_WIDTH;
}
//自己画
paintLine.setColor(frameColor);
// 0x8800FF00
Shader mShader = new LinearGradient(left + CORNER_WIDTH, slideTop, right
- CORNER_WIDTH, slideTop + MIDDLE_LINE_WIDTH,new int[] {Color.TRANSPARENT,frameBaseColor,frameColor,frameColor,frameColor,frameColor,frameColor,frameBaseColor,Color.TRANSPARENT},null, Shader.TileMode.CLAMP);
//新建一个线性渐变,前两个参数是渐变开始的点坐标,第三四个参数是渐变结束的点的坐标。
// 连接这2个点就拉出一条渐变线了,玩过PS的都懂。然后那个数组是渐变的颜色。下一个参数是渐变颜色的分布,如果为空,每个颜色就是均匀分布的。
// 最后是模式,这里设置的是Clamp渐变
paintLine.setShader(mShader);
canvas.drawRect(left + CORNER_WIDTH, slideTop, right
- CORNER_WIDTH, slideTop + MIDDLE_LINE_WIDTH, paintLine);
}*/
/**
* 中间色颜色换算
*/
public int reSetColor(int startInt) {
int startA = (startInt >> 24) & 0xff;
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;
int endA = startA / 2;// 转化后可以设置 2:半透明度 4:4分之一透明度
return ((startA + (endA - startA)) << 24)
| (startR << 16)
| (startG << 8)
| (startB);
}
}
package com.reactnativecomponent.barcode.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.AbsSeekBar;
public class VerticalSeekBar extends AbsSeekBar {
private Drawable mThumb;
public interface OnSeekBarChangeListener {
void onProgressChanged(VerticalSeekBar VerticalSeekBar, int progress, boolean fromUser);
void onStartTrackingTouch(VerticalSeekBar VerticalSeekBar);
void onStopTrackingTouch(VerticalSeekBar VerticalSeekBar);
}
private OnSeekBarChangeListener mOnSeekBarChangeListener;
public VerticalSeekBar(Context context) {
this(context, null);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.seekBarStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
mOnSeekBarChangeListener = l;
}
void onStartTrackingTouch() {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStartTrackingTouch(this);
}
}
void onStopTrackingTouch() {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStopTrackingTouch(this);
}
}
void onProgressRefresh(float scale, boolean fromUser) {
Drawable thumb = mThumb;
if (thumb != null) {
setThumbPos(getHeight(), thumb, scale, Integer.MIN_VALUE);
invalidate();
}
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), isPressed());
}
}
private void setThumbPos(int w, Drawable thumb, float scale, int gap) {
int available = w - getPaddingLeft() - getPaddingRight();
int thumbWidth = thumb.getIntrinsicWidth();
int thumbHeight = thumb.getIntrinsicHeight();
available -= thumbWidth;
// The extra space for the thumb to move on the track
available += getThumbOffset() * 2;
int thumbPos = (int) (scale * available);
int topBound, bottomBound;
if (gap == Integer.MIN_VALUE) {
Rect oldBounds = thumb.getBounds();
topBound = oldBounds.top;
bottomBound = oldBounds.bottom;
} else {
topBound = gap;
bottomBound = gap + thumbHeight;
}
thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);
}
@Override
protected void onDraw(Canvas c) {
c.rotate(-90);// 反转90度,将水平SeekBar竖起来
c.translate(-getHeight(), 0);// 将经过旋转后得到的VerticalSeekBar移到正确的位置,注意经旋转后宽高值互换
super.onDraw(c);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());// 宽高值互换
}
@Override
public void setThumb(Drawable thumb) {
mThumb = thumb;
super.setThumb(thumb);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldw, oldh);// 宽高值互换
}
// 与源码完全相同,仅为调用宽高值互换处理的onStartTrackingTouch()方法
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
setPressed(true);
onStartTrackingTouch();
trackTouchEvent(event);
break;
}
case MotionEvent.ACTION_MOVE: {
trackTouchEvent(event);
attemptClaimDrag();
break;
}
case MotionEvent.ACTION_UP: {
trackTouchEvent(event);
onStopTrackingTouch();
setPressed(false);
// ProgressBar doesn't know to repaint the thumb drawable
// in its inactive state when the touch stops (because the
// value has not apparently changed)
invalidate();
break;
}
case MotionEvent.ACTION_CANCEL: {
onStopTrackingTouch();
setPressed(false);
invalidate(); // see above explanation
break;
}
default:
break;
}
return true;
}
// 宽高值互换处理
private void trackTouchEvent(MotionEvent event) {
final int height = getHeight();
final int available = height - getPaddingBottom() - getPaddingTop();
int Y = (int) event.getY();
float scale;
float progress = 0;
if (Y > height - getPaddingBottom()) {
scale = 0.0f;
} else if (Y < getPaddingTop()) {
scale = 1.0f;
} else {
scale = (float) (height - getPaddingBottom() - Y) / (float) available;
}
final int max = getMax();
progress = scale * max;
setProgress((int) progress);
}
private void attemptClaimDrag() {
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
}
}
/*
* Copyright (C) 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reactnativecomponent.barcode.view;
import com.google.zxing.ResultPoint;
import com.google.zxing.ResultPointCallback;
public final class ViewfinderResultPointCallback implements ResultPointCallback {
private final ViewfinderView viewfinderView;
public ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
this.viewfinderView = viewfinderView;
}
public void foundPossibleResultPoint(ResultPoint point) {
viewfinderView.addPossibleResultPoint(point);
}
}
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@*android:id/background">
<shape>
<solid android:color="#ff51495e" />
</shape>
</item>
<item android:id="@*android:id/secondaryProgress">
<clip>
<shape>
<solid android:color="#ff51495e" />
</shape>
</clip>
</item>
<item android:id="@*android:id/progress">
<clip>
<shape>
<solid android:color="#ff996dfe" />
</shape>
</clip>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="3dip" />
<gradient
android:startColor="#ff9d9e9d"
android:centerColor="#ff5a5d5a"
android:centerY="0.5"
android:endColor="#ff747674"
android:angle="270"
/>
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="3dip" />
<gradient
android:startColor="#ffffd300"
android:centerColor="#ffffb600"
android:centerY="0.5"
android:endColor="#ffffcb00"
android:angle="270"
/>
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="3dip" />
<gradient
android:startColor="#ffffd300"
android:centerColor="#ffffb600"
android:centerY="0.5"
android:endColor="#ffffcb00"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/seekbar_thumb_normal" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/seekbar_thumb_pressed" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/seekbar_thumb_pressed" />
<item android:drawable="@drawable/seekbar_thumb_normal" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.qrcode_zxing.view.VerticalSeekBar
android:id="@+id/verticalSeekBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:progressDrawable="@drawable/seekbar_horizontal"
/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="possible_result_points">#c0ffbd21</color> <!-- Android standard ICS color -->
<color name="result_text">#ff000000</color>
<color name="transparent">#00000000</color>
<color name="viewfinder_laser">#ffcc0000</color> <!-- Android standard ICS color -->
<color name="viewfinder_mask">#cb000000</color>
<color name="viewfinder_frame">#ff4EEE94</color><!-- #ff0000ff -->
<color name="backgroud">#ffffffff</color>
<color name="title_tv_color">#ffffffff</color>
</resources>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2008 ZXing authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Messages IDs -->
<item type="id" name="auto_focus"/>
<item type="id" name="decode"/>
<item type="id" name="decode_failed"/>
<item type="id" name="decode_succeeded"/>
<item type="id" name="encode_failed"/>
<item type="id" name="encode_succeeded"/>
<item type="id" name="launch_product_query"/>
<item type="id" name="quit"/>
<item type="id" name="restart_preview"/>
<item type="id" name="return_scan_result"/>
<item type="id" name="search_book_contents_failed"/>
<item type="id" name="search_book_contents_succeeded"/>
</resources>
<resources>
<string name="app_name">QRCode_Zxing</string>
</resources>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/cyqresig/ReactNativeComponents/react-native-smart-barcode/ios/RCTBarcode/RCTBarCode.xcodeproj">
</FileRef>
</Workspace>
#import <UIKit/UIKit.h>
@interface LineView : UIView
@property (nonatomic, copy) NSString *scannerLineColor;
- (id)initWithScannerLineColor:(NSString*)scannerLineColor frame:(CGRect)frame;
@end
#import "LineView.h"
#import "UIColor+Hex.h"
//#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
@implementation LineView
- (id)initWithScannerLineColor:(NSString*)scannerLineColor frame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
self.scannerLineColor = scannerLineColor;
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
self.backgroundColor = [UIColor clearColor];
// NSArray *colors = @[@0x00000000, @0x8800FF00, @0xFF00FF00, @0xFF00FF00, @0xFF00FF00, @0xFF00FF00, @0xFF00FF00, @0x8800FF00, @0x00000000];
// NSLog(@"@0xFF00FF00 = %@", @0xFF00FF00);
UIColor *scannerLineColor = [UIColor colorWithHexString:self.scannerLineColor];
NSArray *colors = @[scannerLineColor, scannerLineColor, scannerLineColor, scannerLineColor, scannerLineColor, scannerLineColor, scannerLineColor, scannerLineColor, scannerLineColor];
[self _drawGradientColor:context
rect:rect
options:kCGGradientDrawsBeforeStartLocation
colors:colors];
}
/**
* 绘制背景色渐变的矩形,p_colors渐变颜色设置,集合中存储UIColor对象(创建Color时一定用三原色来创建)
**/
- (void)_drawGradientColor:(CGContextRef)p_context rect:(CGRect)p_clipRect options:(CGGradientDrawingOptions)p_options colors:(NSArray *)p_colors {
CGContextSaveGState(p_context);// 保持住现在的context
CGContextClipToRect(p_context, p_clipRect);// 截取对应的context
long colorCount = p_colors.count;
int numOfComponents = 4;
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
CGFloat colorComponents[colorCount * numOfComponents];
CGColorRef temcolorRef = nil;
for (int i = 0; i < colorCount; i++) {
if(i==0){
temcolorRef = [UIColor clearColor].CGColor;
}else if (i==colorCount-1) {
temcolorRef = [UIColor clearColor].CGColor;
}else{
// temcolorRef = UIColorFromRGB([p_colors[i] integerValue]).CGColor;
temcolorRef = ((UIColor *)p_colors[i]).CGColor;
}
const CGFloat *components = CGColorGetComponents(temcolorRef);
for (int j = 0; j < numOfComponents; ++j) {
colorComponents[i * numOfComponents + j] = components[j];
}
}
CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colorComponents, NULL, colorCount);
CGColorSpaceRelease(rgb);
CGPoint startPoint = CGPointMake(0, 0);
CGPoint endPoint = CGPointMake(p_clipRect.size.width, p_clipRect.size.height);
CGContextDrawLinearGradient(p_context, gradient, startPoint, endPoint, p_options);
CGGradientRelease(gradient);
CGContextRestoreGState(p_context);// 恢复到之前的context
}
@end
This diff is collapsed.
This diff is collapsed.
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import "RCTBarcodeManager.h"
#import "LineView.h"
#import "RectView.h";
@interface RCTBarcode : UIView
@property (nonatomic,strong)NSTimer *scanLineTimer;
@property (nonatomic,strong)LineView *scanLine;
@property (nonatomic,assign)CGRect scannerRect;
@property (nonatomic, copy) RCTBubblingEventBlock onBarCodeRead;
@property (nonatomic, assign) NSInteger scannerRectWidth;
@property (nonatomic, assign) NSInteger scannerRectHeight;
@property (nonatomic, assign) NSInteger scannerRectTop;
@property (nonatomic, assign) NSInteger scannerRectLeft;
@property (nonatomic, assign) NSInteger scannerLineInterval;
@property (nonatomic, copy) NSString *scannerRectCornerColor;
- (id)initWithManager:(RCTBarcodeManager*)manager;
- (void)moveUpAndDownLine;
- (void)createTimer;
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment