Commit 962bcd79 authored by JingChao's avatar JingChao

'init'

parents
File added
# cordova-plugin-barcode 二维码扫描Cordova插件
This plugin implements barcode scanner on Cordova 4.0
## Supported Cordova Platforms
* Android 4.0.0 or above
* iOS 7.0.0 or above
## Usage
cordova plugin add https://github.com/MrLiZ/HuiLianYi-barCode.git
## JS
``` js
com.hls.plugins.barcode.startScan({
message:{
barTitle:'标题栏文案',
explainFlag: false,//是否显示说明按钮
title:'扫码上方描述',
tipScan:'扫码下方描述',
inputFlag: true,//是否显示输入按钮
lightFlag: true,//是否显示照亮按钮
tipInput:'输入单号提示',
tipLightOn:'打开照亮提示',
tipLightOff:'关闭照亮提示',
tipLoading:'调接口的过程中的提示',
tipNetworkError:'网络错误时的提示',
tipOffline:'没有打开web时的提示',
openButton:'我已打开按钮文字',
footerFirst:'底部提示第一行,可空',
footerSecond:'底部提示第二行,可空',
delayTime:'1000'
},
operationType:'REVIEW',
requests:[
{
url:'www.huilianyi.com',
method:'POST',
headers:{
Authorization:'Bearer xxxxx',
Content-Type:'xxxx'
},
config: {
timeout: 10000 (单位是毫秒)
},
data:{
code:'xxxx-xxxx',
operate:'xxxx'
}
},
...
]
},function(success){
alert(JSON.stringify(success));
}, function(error){
alert(JSON.stringify(error));
});
```
<?xml version="1.0" encoding="utf-8"?>
<plugin id="com.hls.plugins.barcode" version="0.0.1" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<name>barcode</name>
<description>hls barcode cordova plugin</description>
<engines>
<engine name="cordova" version=">=3.4.0"/>
</engines>
<dependency id="cordova-plugin-compat"></dependency>
<js-module src="www/barcode.js">
<clobbers target="com.hls.plugins.barcode" />
</js-module>
<platform name="android">
<hook type="after_plugin_add" src="scripts/android-install.js" />
<hook type="after_plugin_install" src="scripts/android-install.js" />
<hook type="before_plugin_rm" src="scripts/android-install.js" />
<hook type="before_plugin_uninstall" src="scripts/android-install.js" />
<config-file target="res/xml/config.xml" parent="/*">
<feature name="Barcode">
<param name="android-package" value="com.hls.plugins.barcode.BarcodePlugin"/>
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<activity
android:name="com.hls.plugins.barcode.CaptureActivity"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Light.NoTitleBar" >
</activity>
<activity android:name="com.hls.plugins.barcode.activity.NetWorkErrorActivity" android:screenOrientation="portrait" />
<activity android:name="com.hls.plugins.barcode.activity.UnOpenWebActivity" android:screenOrientation="portrait" />
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-feature android:name="android.hardware.camera.autofocus" />
</config-file>
<source-file src="src/android/libs/arm64-v8a/libzbar.so" target-dir="libs/arm-v8a"/>
<source-file src="src/android/libs/armeabi/libzbar.so" target-dir="libs/armeabi"/>
<source-file src="src/android/libs/armeabi-v7a/libzbar.so" target-dir="libs/armeabi-v7a"/>
<source-file src="src/android/libs/x86/libzbar.so" target-dir="libs/x86"/>
<source-file src="src/android/libs/x86_64/libzbar.so" target-dir="libs/x86_64"/>
<source-file src="src/android/src/com/hls/plugins/barcode/BarcodePlugin.java" target-dir="src/com/hls/plugins/barcode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/CaptureActivity.java" target-dir="src/com/hls/plugins/barcode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/ZbarManager.java" target-dir="src/com/zbar/lib"/>
<source-file src="src/android/src/com/hls/plugins/barcode/camera/AutoFocusCallback.java" target-dir="src/com/hls/plugins/barcode/camera"/>
<source-file src="src/android/src/com/hls/plugins/barcode/camera/CameraConfigurationManager.java" target-dir="src/com/hls/plugins/barcode/camera"/>
<source-file src="src/android/src/com/hls/plugins/barcode/camera/CameraManager.java" target-dir="src/com/hls/plugins/barcode/camera"/>
<source-file src="src/android/src/com/hls/plugins/barcode/camera/FlashlightManager.java" target-dir="src/com/hls/plugins/barcode/camera"/>
<source-file src="src/android/src/com/hls/plugins/barcode/camera/PreviewCallback.java" target-dir="src/com/hls/plugins/barcode/camera"/>
<source-file src="src/android/src/com/hls/plugins/barcode/decode/CaptureActivityHandler.java" target-dir="src/com/hls/plugins/barcode/decode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/decode/DecodeHandler.java" target-dir="src/com/hls/plugins/barcode/decode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/decode/DecodeThread.java" target-dir="src/com/hls/plugins/barcode/decode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/decode/FinishListener.java" target-dir="src/com/hls/plugins/barcode/decode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/decode/InactivityTimer.java" target-dir="src/com/hls/plugins/barcode/decode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/activity/DialogToast.java" target-dir="src/com/hls/plugins/barcode/activity"/>
<source-file src="src/android/src/com/hls/plugins/barcode/activity/IUnOpenWebActivity.java" target-dir="src/com/hls/plugins/barcode/activity"/>
<source-file src="src/android/src/com/hls/plugins/barcode/activity/NetWorkErrorActivity.java" target-dir="src/com/hls/plugins/barcode/activity"/>
<source-file src="src/android/src/com/hls/plugins/barcode/activity/UnOpenWebActivity.java" target-dir="src/com/hls/plugins/barcode/activity"/>
<source-file src="src/android/src/com/hls/plugins/barcode/activity/UnOpenWebActivityPresenter.java" target-dir="src/com/hls/plugins/barcode/activity"/>
<source-file src="src/android/src/com/hls/plugins/barcode/bean/ArgsBean.java" target-dir="src/com/hls/plugins/barcode/bean"/>
<source-file src="src/android/src/com/hls/plugins/barcode/bean/ArgsBiz.java" target-dir="src/com/hls/plugins/barcode/bean"/>
<source-file src="src/android/src/com/hls/plugins/barcode/bean/CodeInfoBean.java" target-dir="src/com/hls/plugins/barcode/bean"/>
<source-file src="src/android/src/com/hls/plugins/barcode/bean/HttpInfoBean.java" target-dir="src/com/hls/plugins/barcode/bean"/>
<source-file src="src/android/src/com/hls/plugins/barcode/bean/PageInfoBean.java" target-dir="src/com/hls/plugins/barcode/bean"/>
<source-file src="src/android/src/com/hls/plugins/barcode/http/HttpManager.java" target-dir="src/com/hls/plugins/barcode/http"/>
<source-file src="src/android/src/com/hls/plugins/barcode/http/HttpUtil.java" target-dir="src/com/hls/plugins/barcode/http"/>
<source-file src="src/android/src/com/hls/plugins/barcode/http/ResultCallback.java" target-dir="src/com/hls/plugins/barcode/http"/>
<source-file src="src/android/src/com/hls/plugins/barcode/Util/Util.java" target-dir="src/com/hls/plugins/barcode/Util"/>
<source-file src="src/android/src/com/hls/plugins/barcode/Util/NoSSLv3SocketFactory.java" target-dir="src/com/hls/plugins/barcode/Util"/>
<source-file src="src/android/src/com/hls/plugins/barcode/CapturePresenter.java" target-dir="src/com/hls/plugins/barcode"/>
<source-file src="src/android/src/com/hls/plugins/barcode/ICaptureActivity.java" target-dir="src/com/hls/plugins/barcode"/>
<source-file src="src/android/res/drawable/corner_input.xml" target-dir="res/drawable"/>
<source-file src="src/android/res/drawable/corner_input_pressed.xml" target-dir="res/drawable"/>
<source-file src="src/android/res/drawable/corner_textview.xml" target-dir="res/drawable"/>
<source-file src="src/android/res/drawable/corner_textview_pressed.xml" target-dir="res/drawable"/>
<source-file src="src/android/res/drawable/progress_custom_bg.xml" target-dir="res/drawable"/>
<source-file src="src/android/res/drawable/selector_input.xml" target-dir="res/drawable"/>
<source-file src="src/android/res/drawable/selector_open_web.xml" target-dir="res/drawable"/>
<source-file src="src/android/res/drawable-hdpi/cancel.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/network_error.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/pc.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/pen.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/btn_back.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/input.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/tip.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/light.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/drawable-hdpi/light_close.png" target-dir="res/drawable-hdpi"/>
<source-file src="src/android/res/layout/activity_network_error.xml" target-dir="res/layout"/>
<source-file src="src/android/res/layout/activity_unopen_web.xml" target-dir="res/layout"/>
<source-file src="src/android/res/layout/dialog_cancel_layout.xml" target-dir="res/layout"/>
<source-file src="src/android/res/values/dialog_style.xml" target-dir="res/values"/>
<source-file src="src/android/res/drawable-xhdpi/btn_flash.xml" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/drawable-xhdpi/capture.9.png" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/drawable-xhdpi/common_titlebar_btn_back_light.png" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/drawable-xhdpi/common_titlebar_btn_back_light_pressed.png" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/drawable-xhdpi/kakalib_scan_ray.png" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/drawable-xhdpi/qrcode_ligth_on_normal.png" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/drawable-xhdpi/qrcode_ligth_on_pressed.png" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/drawable-xhdpi/scan_line.png" target-dir="res/drawable-xhdpi"/>
<source-file src="src/android/res/layout/activity_qr_scan.xml" target-dir="res/layout"/>
<source-file src="src/android/res/values/ids.xml" target-dir="res/values"/>
<source-file src="src/android/res/raw/beep.ogg" target-dir="res/raw"/>
</platform>
<platform name="ios">
<config-file target="config.xml" parent="/widget">
<feature name="Barcode">
<param name="ios-package" value="CDVBarcodeScanner" />
</feature>
</config-file>
<config-file target="*-Info.plist" parent="NSCameraUsageDescription">
<string>Whether or not allowed?</string>
</config-file>
<config-file target="*-Info.plist" parent="NSPhotoLibraryUsageDescription">
<string>Whether or not allowed?</string>
</config-file>
<resource-file src="src/ios/res/BarcodeScannerViewController.xib" />
<resource-file src="src/ios/res/beep.wav" />
<resource-file src="src/ios/res/scan_1@2x.png" />
<resource-file src="src/ios/res/scan_2@2x.png" />
<resource-file src="src/ios/res/scan_3@2x.png" />
<resource-file src="src/ios/res/scan_4@2x.png" />
<resource-file src="src/ios/res/hly_alertimg@2x.png" />
<resource-file src="src/ios/res/hly_alertimg@3x.png" />
<resource-file src="src/ios/res/hly_backimg@2x.png" />
<resource-file src="src/ios/res/hly_backimg@3x.png" />
<resource-file src="src/ios/res/hly_handwork@2x.png" />
<resource-file src="src/ios/res/hly_handwork@3x.png" />
<resource-file src="src/ios/res/hly_line_scan@2x.png" />
<resource-file src="src/ios/res/light_close@2x.png" />
<resource-file src="src/ios/res/light_close@3x.png" />
<resource-file src="src/ios/res/light_open@2x.png" />
<resource-file src="src/ios/res/light_open@3x.png" />
<resource-file src="src/ios/res/hly_write.png" />
<resource-file src="src/ios/res/hly_net.png" />
<resource-file src="src/ios/res/hly_pc.png" />
<header-file src="src/ios/src/BarcodeScannerViewController.h" />
<source-file src="src/ios/src/BarcodeScannerViewController.m" />
<header-file src="src/ios/src/CDVBarcodeScanner.h" />
<source-file src="src/ios/src/CDVBarcodeScanner.m" />
<header-file src="src/ios/src/CustomScanView.h" />
<source-file src="src/ios/src/CustomScanView.m" />
<header-file src="src/ios/src/Reachability.h" />
<source-file src="src/ios/src/Reachability.m" />
<header-file src="src/ios/src/UIView+Toast.h" />
<source-file src="src/ios/src/UIView+Toast.m" />
<header-file src="src/ios/src/HLYCustomButton.h" />
<source-file src="src/ios/src/HLYCustomButton.m" />
</platform>
</plugin>
#!/usr/bin/env node
module.exports = function (context) {
var path = context.requireCordovaModule('path'),
fs = context.requireCordovaModule('fs'),
shell = context.requireCordovaModule('shelljs'),
projectRoot = context.opts.projectRoot,
ConfigParser = context.requireCordovaModule('cordova-common').ConfigParser,
config = new ConfigParser(path.join(context.opts.projectRoot, "config.xml")),
packageName = config.android_packageName() || config.packageName();
if (!packageName) {
console.error("Package name could not be found!");
return ;
}
if (context.opts.cordova.platforms.indexOf("android") === -1) {
console.info("Android platform has not been added.");
return ;
}
var targetDir = path.join(projectRoot, "platforms", "android", "src", "com", "hls", "plugins", "barcode");
var targetFiles = ["CaptureActivity.java", "decode/DecodeHandler.java", "decode/CaptureActivityHandler.java","activity/DialogToast.java","activity/NetWorkErrorActivity.java","activity/UnOpenWebActivity.java"];
if (['after_plugin_add', 'after_plugin_install', 'after_platform_add'].indexOf(context.hook) === -1) {
try {
if(context.opts.plugins && context.opts.plugins.indexOf(context.opts.plugin.id) !== -1){
targetFiles.forEach(function(file){
var targetFile = path.join(targetDir, file);
fs.unlinkSync(targetFile);
});
}
} catch (err) {}
} else {
targetFiles.forEach(function(file){
var targetFile = path.join(targetDir, file);
fs.readFile(targetFile, {encoding: 'utf-8'}, function (err, data) {
if (err) {
throw err;
}
data = data.replace(/^import __ANDROID_PACKAGE__.R;/m, 'import ' + packageName + '.R;');
fs.writeFileSync(targetFile, data);
});
});
}
};
\ No newline at end of file
File added
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="@drawable/qrcode_ligth_on_normal" />
<item android:state_pressed="true" android:drawable="@drawable/qrcode_ligth_on_pressed" />
<item android:state_focused="true" android:drawable="@drawable/qrcode_ligth_on_pressed" />
<item android:drawable="@drawable/qrcode_ligth_on_normal" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#91918d" />
<corners android:radius="25dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#5591918d" />
<corners android:radius="25dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#0092DA" />
<corners android:radius="30dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#0c72a4" />
<corners android:radius="30dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#ff404040" />
<corners
android:bottomLeftRadius="50dp"
android:bottomRightRadius="50dp"
android:topLeftRadius="50dp"
android:topRightRadius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="@drawable/corner_input" />
<item android:state_pressed="true" android:drawable="@drawable/corner_input_pressed" />
<item android:state_focused="true" android:drawable="@drawable/corner_input_pressed" />
<item android:drawable="@drawable/corner_input" />
</selector>
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="@drawable/corner_textview" />
<item android:state_pressed="true" android:drawable="@drawable/corner_textview_pressed" />
<item android:state_focused="true" android:drawable="@drawable/corner_textview_pressed" />
<item android:drawable="@drawable/corner_textview" />
</selector>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
>
<ImageView
android:id="@+id/imgBtnBack"
android:layout_width="44dp"
android:layout_height="44dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:background="#00000000"
android:clickable="true"
android:src="@drawable/btn_back" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="22sp"
android:layout_centerInParent="true"
android:text="扫一扫"
/>
</RelativeLayout>
<ImageView
android:id="@+id/img_network_error"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/network_error"
android:layout_centerHorizontal="true"
android:layout_marginTop="130dp"
/>
<TextView
android:id="@+id/txt_tipNetworkError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="@android:color/white"
android:text="当前网络不可用,请检查网络设置"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:layout_below="@+id/img_network_error"
/>
<TextView
android:id="@+id/txt_tip1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="38dp"
android:textColor="@android:color/white"
android:text="123"
android:textSize="15sp" />
<TextView
android:id="@+id/txt_tip2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:textColor="@android:color/white"
android:text="456"
android:textSize="15sp" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/capture_containter"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/capture_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/top_mask"
android:layout_width="match_parent"
android:layout_height="110dp"
android:layout_alignParentTop="true"
android:background="#EE010713" />
<RelativeLayout
android:id="@+id/capture_crop_layout"
android:layout_width="220dp"
android:layout_height="220dp"
android:layout_below="@id/top_mask"
android:layout_centerHorizontal="true"
android:background="@drawable/capture">
<ImageView
android:id="@+id/capture_scan_line"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_margin="5dp"
android:src="@drawable/kakalib_scan_ray" />
</RelativeLayout>
<ImageView
android:id="@+id/bottom_mask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_below="@+id/capture_crop_layout"
android:background="#EE010713" />
<ImageView
android:id="@+id/left_mask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom_mask"
android:layout_alignParentLeft="true"
android:layout_below="@id/top_mask"
android:layout_toLeftOf="@id/capture_crop_layout"
android:background="#EE010713" />
<ImageView
android:id="@+id/right_mask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom_mask"
android:layout_alignParentRight="true"
android:layout_below="@id/top_mask"
android:layout_toRightOf="@id/capture_crop_layout"
android:background="#EE010713" />
<TextView
android:id="@+id/txtScanTip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/capture_crop_layout"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="请扫描单据上的二维码"
android:textColor="#808080"
android:textSize="14dp" />
<LinearLayout
android:layout_width="240dp"
android:layout_height="90dp"
android:layout_below="@id/capture_crop_layout"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/lyt_input"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="54dp"
android:layout_height="54dp"
android:src="@drawable/input" />
<TextView
android:id="@+id/txt_input"
android:layout_width="110dp"
android:layout_height="30dp"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:text="手工输入"
android:textColor="#FFFFFF"
android:textSize="14dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/lyt_light"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/img_light"
android:layout_width="54dp"
android:layout_height="54dp"
android:src="@drawable/light" />
<TextView
android:id="@+id/txt_light"
android:layout_width="110dp"
android:layout_height="30dp"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:text="打开照亮"
android:textColor="#FFFFFF"
android:textSize="14dp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/txt_tip1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="38dp"
android:textColor="#808080"
android:textSize="14dp" />
<TextView
android:id="@+id/txt_tip2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:textColor="#808080"
android:textSize="14dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<ImageView
android:id="@+id/imgBtnBack"
android:layout_width="44dp"
android:layout_height="44dp"
android:background="#00000000"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:src="@drawable/btn_back" />
<TextView
android:id="@+id/txt_title"
android:layout_width="100dp"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:gravity="center"
android:singleLine="false"
android:text="扫 一 扫"
android:textColor="@android:color/white"
android:textSize="18dp" />
<RelativeLayout
android:id="@+id/rel_tip"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_marginRight="12dp"
android:layout_alignParentRight="true">
<ImageView
android:id="@+id/img_tip"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/tip" />
</RelativeLayout>
</RelativeLayout>
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/top_mask"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="锁定审核驳回"
android:textColor="#808080"
android:textSize="14dp" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
>
<ImageView
android:id="@+id/imgBtnBack"
android:layout_width="44dp"
android:layout_height="44dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:background="#00000000"
android:src="@drawable/btn_back" />
<TextView
android:id="@+id/scanTitile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="22sp"
android:layout_centerInParent="true"
android:text="扫一扫"
/>
</RelativeLayout>
<ImageView
android:id="@+id/img_pc"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/pc"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
/>
<TextView
android:id="@+id/txt_tipOffLine"
android:layout_width="176dp"
android:gravity="center"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="@android:color/white"
android:text="请按照页面下方提示先打开汇联易网站"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:layout_below="@+id/img_pc"
/>
<TextView
android:id ="@+id/txt_open"
android:layout_width="180dp"
android:layout_height="60dp"
android:gravity="center"
android:text="我已打开"
android:clickable="true"
android:textColor="@android:color/white"
android:textSize="22sp"
android:layout_centerHorizontal="true"
android:layout_below="@+id/txt_tipOffLine"
android:layout_marginTop="30dp"
android:background="@drawable/selector_open_web"
/>
<TextView
android:id="@+id/txt_tip1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="38dp"
android:textColor="@android:color/white"
android:text="123"
android:textSize="15sp" />
<TextView
android:id="@+id/txt_tip2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:textColor="@android:color/white"
android:text="456"
android:textSize="15sp" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/progress_custom_bg"
android:paddingRight="25dp"
android:paddingLeft="25dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
>
<TextView
android:id = "@+id/txt_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="22sp"
android:text="正在处理"
android:textColor="#FFFFFF"
/>
<View
android:layout_width="1dp"
android:layout_height="24dp"
android:background="#FFFFFF"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
/>
<ImageView
android:id = "@+id/txt_cancel"
android:layout_width="24dp"
android:layout_height="24dp"
android:gravity="center"
android:src="@drawable/cancel"
android:textColor="#FFFFFF"
android:fontFamily="monospace"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 自定义Dialog -->
<style name="Custom_Progress" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="auto_focus" type="id"/>
<item name="decode" type="id"/>
<item name="decode_failed" type="id"/>
<item name="decode_succeeded" type="id"/>
<item name="restart_preview" type="id"/>
<item name="quit" type="id"/>
</resources>
\ No newline at end of file
package com.hls.plugins.barcode;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.util.Log;
import android.widget.Toast;
import com.hls.plugins.barcode.Util.Util;
import com.hls.plugins.barcode.activity.NetWorkErrorActivity;
import com.hls.plugins.barcode.activity.UnOpenWebActivity;
import com.hls.plugins.barcode.bean.ArgsBean;
import com.hls.plugins.barcode.bean.ArgsBiz;
/**
* Created by Administrator on 2016/3/16.
*/
public class BarcodePlugin extends CordovaPlugin {
public static CallbackContext cbContext = null;
private static final String LOG_TAG = "BarcodeScanner";
private String[] permissions = {Manifest.permission.CAMERA};
private JSONArray args;
@Override
public boolean execute(String action, final JSONArray args, CallbackContext callbackContext) throws JSONException {
cbContext = callbackContext;
if (action.equals("startScan")) {
this.args =args;
if (!hasPermission()) {
requestPermissions(0);
} else {
scan(args);
}
} else if (action.equals("hasPermission")) {
if (!hasPermission()) {
requestPermissions(0);
}
cbContext.success(hasPermission() + "");
return true;
}
return true;
}
/**
* Starts an intent to scan and decode a barcode.
*/
public void scan(final JSONArray args) {
try {
ArgsBiz argsBiz = new ArgsBiz();
ArgsBean argsBean ;
argsBean = argsBiz.getArgsBeanByJSONObject(args.getJSONObject(0));
if (!Util.isNetworkAvailable(cordova.getActivity())) {
Intent intent = new Intent(cordova.getActivity(), NetWorkErrorActivity.class);
intent.putExtra("ARGS",argsBean);
this.cordova.getActivity().startActivity(intent);
return;
}
if(argsBean!=null) {
Intent intentScan = new Intent(this.cordova.getActivity().getApplicationContext(), CaptureActivity.class);
intentScan.putExtra("ARGS", argsBean);
this.cordova.getActivity().startActivity(intentScan);
}else{
cbContext.success("请检查参数");
}
} catch (JSONException e) {
e.printStackTrace();
cbContext.success("请检查参数");
}
}
/**
* check application's permissions
*/
public boolean hasPermission() {
for (String p : permissions) {
if (!PermissionHelper.hasPermission(this, p)) {
return false;
} else {
boolean isCanUse = true;
Camera mCamera = null;
try {
mCamera = Camera.open();
Camera.Parameters mParameters = mCamera.getParameters(); // 针对魅族手机
mCamera.setParameters(mParameters);
} catch (Exception e) {
isCanUse = false;
}
if (mCamera != null) {
try {
mCamera.release();
} catch (Exception e) {
e.printStackTrace();
return isCanUse;
}
}
return isCanUse;
}
}
return true;
}
/**
* We override this so that we can access the permissions variable, which no
* longer exists in the parent class, since we can't initialize it reliably
* in the constructor!
*
* @param requestCode The code to get request action
*/
public void requestPermissions(int requestCode) {
PermissionHelper.requestPermissions(this, requestCode, permissions);
}
/**
* processes the result of permission request
*
* @param requestCode The code to get request action
* @param permissions The collection of permissions
* @param grantResults The result of grant
*/
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults)
throws JSONException {
PluginResult result;
// Toast.makeText(this.cordova.getActivity().getApplicationContext(), grantResults.toString(), 3).show();
for (int r : grantResults) {
if (r == PackageManager.PERMISSION_DENIED) {
Log.d(LOG_TAG, "Permission Denied!");
result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
cbContext.sendPluginResult(result);
return;
}
}
if(args!=null){
scan(args);
}
}
}
package com.hls.plugins.barcode;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import __ANDROID_PACKAGE__.R;
import com.hls.plugins.barcode.Util.Util;
import com.hls.plugins.barcode.activity.DialogToast;
import com.hls.plugins.barcode.activity.NetWorkErrorActivity;
import com.hls.plugins.barcode.activity.UnOpenWebActivity;
import com.hls.plugins.barcode.bean.ArgsBean;
import com.hls.plugins.barcode.camera.CameraManager;
import com.hls.plugins.barcode.decode.CaptureActivityHandler;
import com.hls.plugins.barcode.decode.InactivityTimer;
import com.hls.plugins.barcode.http.HttpManager;
import com.hls.plugins.barcode.http.ResultCallback;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Color;
import android.graphics.Point;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.ScaleAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
public class CaptureActivity extends Activity implements Callback, ICaptureActivity, View.OnClickListener {
private final static String TAG = "CaptureActivity";
private ProgressDialog progressDialog;
private CaptureActivityHandler handler;
private boolean hasSurface;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = 0.50f;
private boolean vibrate;
private int x = 0;
private int y = 0;
private int cropWidth = 0;
private int cropHeight = 0;
private RelativeLayout mContainer = null;
private RelativeLayout mCropLayout = null;
private TextView tv_type = null;
private TextView tv_lable1 = null;
private TextView tv_lable2 = null;
private TextView tv_scanTip = null;
private LinearLayout lytInput = null;
private LinearLayout lytLight = null;
private TextView mTipLight;
private ImageView mImgLight;
private ImageView imgTip = null;
private CapturePresenter capturePresenter;
private ArgsBean argsBean;
private DialogToast dialogToast;
private boolean finishFlag;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getCropWidth() {
return cropWidth;
}
public void setCropWidth(int cropWidth) {
this.cropWidth = cropWidth;
}
public int getCropHeight() {
return cropHeight;
}
public void setCropHeight(int cropHeight) {
this.cropHeight = cropHeight;
}
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qr_scan);
capturePresenter = new CapturePresenter(this, this);
readIntent();
// 初始化 CameraManager
CameraManager.init(getApplication());
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
mContainer = (RelativeLayout) findViewById(R.id.capture_containter);
mCropLayout = (RelativeLayout) findViewById(R.id.capture_crop_layout);
tv_type = (TextView) findViewById(R.id.tv_type);
tv_lable1 = (TextView) findViewById(R.id.txt_tip1);
tv_lable2 = (TextView) findViewById(R.id.txt_tip2);
tv_scanTip = (TextView) findViewById(R.id.txtScanTip);
lytInput = (LinearLayout) findViewById(R.id.lyt_input);
lytLight = (LinearLayout) findViewById(R.id.lyt_light);
imgTip = (ImageView) findViewById(R.id.img_tip);
mTipLight = (TextView) findViewById(R.id.txt_light);
mImgLight = (ImageView) findViewById(R.id.img_light);
initData();
ImageView mQrLineView = (ImageView) findViewById(R.id.capture_scan_line);
ScaleAnimation animation = new ScaleAnimation(1.0f, 1.0f, 0.0f, 1.0f);
animation.setRepeatCount(-1);
animation.setRepeatMode(Animation.RESTART);
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(1200);
mQrLineView.startAnimation(animation);
setButtonListeners();
}
private void readIntent() {
argsBean = getIntent().getParcelableExtra("ARGS");
flag = getIntent().getBooleanExtra("light", true);
if (!flag) {
new Handler(getMainLooper()).post(new Runnable() {
@Override
public void run() {
CameraManager.get().openLight();
}
});
}
}
private void initData() {
tv_type.setText(argsBean.getPageInfoBean().getTitle());
tv_lable1.setText(argsBean.getPageInfoBean().getFooterFirst());
tv_lable2.setText(argsBean.getPageInfoBean().getFooterSecond());
tv_scanTip.setText(argsBean.getPageInfoBean().getTipScan());
if (argsBean.getPageInfoBean().isExplainFlag()) {
imgTip.setVisibility(View.VISIBLE);
} else {
imgTip.setVisibility(View.GONE);
}
((TextView) findViewById(R.id.txt_title)).setText(argsBean.getPageInfoBean().getBarTitle());
if (argsBean.getPageInfoBean().isInputFlag()) {
lytInput.setVisibility(View.VISIBLE);
} else {
lytInput.setVisibility(View.GONE);
}
if (argsBean.getPageInfoBean().isLightFlag()) {
lytLight.setVisibility(View.VISIBLE);
} else {
lytLight.setVisibility(View.GONE);
}
((TextView) findViewById(R.id.txt_input)).setText(argsBean.getPageInfoBean().getTipInput());
mTipLight.setText(argsBean.getPageInfoBean().getTipLightOn() + "");
}
boolean flag = true;
protected void light() {
if (flag == true) {
flag = false;
CameraManager.get().openLight();
mTipLight.setText(argsBean.getPageInfoBean().getTipLightOff() + "");
mImgLight.setImageDrawable(getResources().getDrawable(R.drawable.light_close));
mTipLight.setTextColor(Color.parseColor("#1978d2"));
} else {
flag = true;
CameraManager.get().offLight();
mTipLight.setText(argsBean.getPageInfoBean().getTipLightOn() + "");
mImgLight.setImageDrawable(getResources().getDrawable(R.drawable.light));
mTipLight.setTextColor(Color.parseColor("#FFFFFF"));
}
}
protected void setButtonListeners() {
findViewById(R.id.imgBtnBack).setOnClickListener(this);
lytInput.setOnClickListener(this);
lytLight.setOnClickListener(this);
findViewById(R.id.rel_tip).setOnClickListener(this);
}
@SuppressWarnings("deprecation")
@Override
protected void onResume() {
super.onResume();
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.capture_preview);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true;
}
@Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
CameraManager.get().closeDriver();
}
@Override
public void onBackPressed() {
super.onBackPressed();
JSONObject object = new JSONObject();
try {
object.put("type", "CLOSE");
object.put("message", "{}");
BarcodePlugin.cbContext.success(object);
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("huangjie", "回掉");
BarcodePlugin.cbContext.success(object);
finish();
}
@Override
public void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}
public void handleDecode(final String result) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
if (ArgsBean.SCAN.equals(argsBean.getOperateMethod())) {
JSONObject object = new JSONObject();
try {
object.put("type", ArgsBean.SCAN);
JSONObject messageObject = new JSONObject();
messageObject.put("code", result);
object.put("message", messageObject);
Log.e(TAG, object.toString() + "");
scanFinish(object);
} catch (JSONException e) {
e.printStackTrace();
}
return;
} else if (argsBean.getHttpInfos() == null) {
BarcodePlugin.cbContext.success(result);
finish();
return;
} else
capturePresenter.toValidation(argsBean, result);
}
private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
Point point = CameraManager.get().getCameraResolution();
int width = point.y;
int height = point.x;
int x = mCropLayout.getLeft() * width / mContainer.getWidth();
int y = mCropLayout.getTop() * height / mContainer.getHeight();
int cropWidth = mCropLayout.getWidth() * width
/ mContainer.getWidth();
int cropHeight = mCropLayout.getHeight() * height
/ mContainer.getHeight();
setX(x);
setY(y);
setCropWidth(cropWidth);
setCropHeight(cropHeight);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(CaptureActivity.this);
}
}
@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 Handler getHandler() {
return handler;
}
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);
}
}
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
};
/**
* 将后端数据返回给前端并退出
*
* @param result
*/
@Override
public void scanFinish(final JSONObject result) {
Handler handler = new Handler(getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
BarcodePlugin.cbContext.success(result);
finish();
}
}, 700);
}
@Override
public void ToastCenter(String msg) {
Toast toast = Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
@Override
public void showProgressDialog(boolean isShow) {
if (dialogToast == null && isShow) {
DialogToast.Builder builder = new DialogToast.Builder(this);
dialogToast = builder.setMsg(argsBean.getPageInfoBean().getTipLoading())
.setOnClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
reStartActivity();
}
}).create();
dialogToast.show();
} else if (isShow) {
dialogToast.show();
} else if (!isShow && dialogToast != null) {
dialogToast.dismiss();
}
}
@Override
public void goNetworkErrorPage() {
Intent intent = new Intent(this, NetWorkErrorActivity.class);
intent.putExtra("ARGS", argsBean);
startActivity(intent);
}
@Override
public void goUnOpenWebPage() {
Intent intent = new Intent(this, UnOpenWebActivity.class);
intent.putExtra("ARGS", argsBean);
startActivity(intent);
}
@Override
public void reStartActivity() {
Intent intent = getIntent();
intent.putExtra("light", flag);
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
overridePendingTransition(0, 0);
startActivity(intent);
}
private void input() {
JSONObject object = new JSONObject();
try {
object.put("type", "INPUT");
object.put("message", "{}");
BarcodePlugin.cbContext.success(object);
} catch (JSONException e) {
e.printStackTrace();
}
finish();
}
@Override
public void finish() {
if (argsBean.getPageInfoBean().getDelayTime() != 0 && !finishFlag) {
TimerTask task = new TimerTask() {
@Override
public void run() {
finishFlag = true;
CaptureActivity.this.finish();
}
};
Timer timer = new Timer();
timer.schedule(task, argsBean.getPageInfoBean().getDelayTime());
} else {
super.finish();
}
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.imgBtnBack:
onBackPressed();
break;
case R.id.lyt_input:
input();
break;
case R.id.lyt_light:
light();
break;
case R.id.rel_tip:
JSONObject object = new JSONObject();
try {
object.put("type", "EXPLAIN");
object.put("message", new JSONObject());
scanFinish(object);
} catch (JSONException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
}
package com.hls.plugins.barcode;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.hls.plugins.barcode.Util.Util;
import com.hls.plugins.barcode.bean.ArgsBean;
import com.hls.plugins.barcode.bean.CodeInfoBean;
import com.hls.plugins.barcode.http.HttpManager;
import com.hls.plugins.barcode.http.ResultCallback;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by panx on 2017/3/16.
*/
public class CapturePresenter {
private ICaptureActivity iCaptureActivity;
private Context context;
private final static String TAG = "CapturePresenter";
private ArgsBean argsBean;
public CapturePresenter(ICaptureActivity iCaptureActivity,Context context) {
this.iCaptureActivity = iCaptureActivity;
this.context = context;
}
/**
* 向后端发送验证请求
* @param argsBean
* @param code
*/
public void toValidation(ArgsBean argsBean,final String code) {
this.argsBean = makeArguments(argsBean, code);
if (argsBean == null) return;
iCaptureActivity.showProgressDialog(true);
HttpManager.post(argsBean.getHttpInfos().get(0), new ResultCallback<String>() {
//条码处理失败
@Override
public void onError(Exception e, String error) {
iCaptureActivity.showProgressDialog(false);
iCaptureActivity.ToastCenter(error);
if(!Util.isNetworkAvailable(context)){
iCaptureActivity.goNetworkErrorPage();
}else{
iCaptureActivity.reStartActivity();
}
}
//条码处理成功
@Override
public void onResponse(String response, String extra) {
iCaptureActivity.showProgressDialog(false);
CodeInfoBean codeInfoBean = doCodeResult(response);
if(codeInfoBean!=null) {
doResultBiz(codeInfoBean, response,code);
}else{
iCaptureActivity.ToastCenter(HttpManager.NETWORK_ERROR);
}
}
});
}
/**
* 处理网络请求参数
* @param argsBean
* @param code
* @return
*/
private ArgsBean makeArguments(ArgsBean argsBean, String code) {
String data = argsBean.getHttpInfos().get(0).getData();
try {
JSONObject object = new JSONObject(data);
object.put("code", code);
object.put("operate", argsBean.getOperateMethod());
argsBean.getHttpInfos().get(0).setData(object.toString());
} catch (JSONException e) {
e.printStackTrace();
Log.e(TAG, "wrog arguments for http data");
return null;
}
return argsBean;
}
/**
* 处理扫码结果
*/
private CodeInfoBean doCodeResult(String response) {
Log.e(TAG, response);
try {
JSONObject object = new JSONObject(response);
CodeInfoBean codeInfoBean = new CodeInfoBean();
codeInfoBean.setCode(object.getString(CodeInfoBean.CODE));
codeInfoBean.setMsg(object.getString(CodeInfoBean.MSG));
codeInfoBean.setOnline(object.optString(CodeInfoBean.ONLINE));
codeInfoBean.setExpenseReport(object.optString(CodeInfoBean.EXPENSE_REPORT));
return codeInfoBean;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
/**
* 根据扫码结果做出相应的反馈
*/
private void doResultBiz(CodeInfoBean codeInfoBean, String response,String code) {
String operateMethod = argsBean.getOperateMethod();
if (operateMethod != null && operateMethod.equals(ArgsBean.REVIEW)) {
doReviewBiz(codeInfoBean, response);
} else if (operateMethod != null && operateMethod.equals(ArgsBean.AUDIT_PASS)) {
doAuditPassBiz(codeInfoBean, response);
} else if (operateMethod != null && operateMethod.equals(ArgsBean.AUDIT)) {
doAuditBiz(codeInfoBean, response, code);
}else if (operateMethod != null && operateMethod.equals(ArgsBean.BACK)) {
doBackBiz(codeInfoBean, response, code);
}
else if (operateMethod != null && operateMethod.equals(ArgsBean.RECEIVE)) {
doReceiveBiz(codeInfoBean,response);
} else if (operateMethod != null && operateMethod.equals(ArgsBean.INVOICE)){
doInvoiceBiz(codeInfoBean,response,code);
}
}
/**
* 处理REVIEW的业务逻辑
*/
private void doReviewBiz(CodeInfoBean codeInfoBean, String response) {
if (codeInfoBean.getCode() != null && codeInfoBean.getCode().equals(CodeInfoBean.SUCCESS)) {
//审核成功
JSONObject object = new JSONObject();
try {
object.put("type", ArgsBean.REVIEW);
JSONObject responseObject = new JSONObject(response);
object.put("message", responseObject);
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.scanFinish(object);
} catch (JSONException e) {
e.printStackTrace();
}
} else if (codeInfoBean.getOnline() == null || !codeInfoBean.getOnline().equals("1")) {
iCaptureActivity.goUnOpenWebPage();//未打开中控页面
} else {
//审核没有成功
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.reStartActivity();
}
}
/**
* 处理ADDIT_PASS逻辑
*/
private void doAuditPassBiz(CodeInfoBean codeInfoBean, String response) {
if(codeInfoBean.getCode()!=null && codeInfoBean.getCode().equals(CodeInfoBean.SUCCESS)){
try {
JSONObject object = new JSONObject(codeInfoBean.getExpenseReport());
String applicantName = object.getString("applicantName");
String businessCode = object.getString("businessCode");
String msg = String.format("%s\n%s\n%s",applicantName,businessCode,codeInfoBean.getMsg());
iCaptureActivity.ToastCenter(msg);
} catch (JSONException e) {
e.printStackTrace();
}
iCaptureActivity.reStartActivity();
}else{
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.reStartActivity();
}
}
/**
* 处理AUDIT逻辑
*/
private void doAuditBiz(CodeInfoBean codeInfoBean, String response,String code) {
if(codeInfoBean.getCode()!=null && codeInfoBean.getCode().equals(CodeInfoBean.SUCCESS)){
JSONObject object = new JSONObject();
try {
object.put("type","AUDIT");
JSONObject msgObject = new JSONObject();
msgObject.put("code",code);
JSONObject responseObject = new JSONObject(response);
msgObject.put("response",responseObject);
object.put("message",msgObject);
} catch (JSONException e) {
e.printStackTrace();
}
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.scanFinish(object);
}else{
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.reStartActivity();
}
}
/**
* 处理BACK逻辑
*/
private void doBackBiz(CodeInfoBean codeInfoBean, String response,String code) {
if(codeInfoBean.getCode()!=null && codeInfoBean.getCode().equals(CodeInfoBean.SUCCESS)){
JSONObject object = new JSONObject();
try {
object.put("type","BACK");
JSONObject msgObject = new JSONObject();
msgObject.put("code",code);
JSONObject responseObject = new JSONObject(response);
msgObject.put("response",responseObject);
object.put("message",msgObject);
} catch (JSONException e) {
e.printStackTrace();
}
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.scanFinish(object);
}else{
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.reStartActivity();
}
}
/**
* 处理INVOICE逻辑
*/
private void doInvoiceBiz(CodeInfoBean codeInfoBean, String response,String code) {
if(codeInfoBean.getCode()!=null && codeInfoBean.getCode().equals(CodeInfoBean.SUCCESS)){
JSONObject object = new JSONObject();
try {
object.put("type",ArgsBean.INVOICE);
JSONObject msgObject = new JSONObject();
msgObject.put("code",code);
JSONObject responseObject = new JSONObject(response);
msgObject.put("response",responseObject);
object.put("message",msgObject);
} catch (JSONException e) {
e.printStackTrace();
}
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.scanFinish(object);
}else{
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.reStartActivity();
}
}
/**
* 处理RECEIVE逻辑
*/
private void doReceiveBiz(CodeInfoBean codeInfoBean, String response) {
iCaptureActivity.ToastCenter(codeInfoBean.getMsg());
iCaptureActivity.reStartActivity();
}
}
package com.hls.plugins.barcode;
import org.json.JSONObject;
/**
* Created by panx on 2017/3/16.
*/
public interface ICaptureActivity {
void goNetworkErrorPage();
void goUnOpenWebPage();
void reStartActivity();
void scanFinish(JSONObject result);
void ToastCenter(String msg);
void showProgressDialog(boolean flag);
}
package com.hls.plugins.barcode.Util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class NoSSLv3SocketFactory extends SSLSocketFactory{
private final SSLSocketFactory delegate;
public NoSSLv3SocketFactory() {
this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();
}
public NoSSLv3SocketFactory(SSLSocketFactory delegate) {
this.delegate = delegate;
}
@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
private Socket makeSocketSafe(Socket socket) {
if (socket instanceof SSLSocket) {
socket = new NoSSLv3SSLSocket((SSLSocket) socket);
}
return socket;
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return makeSocketSafe(delegate.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException {
return makeSocketSafe(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return makeSocketSafe(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort));
}
private class NoSSLv3SSLSocket extends DelegateSSLSocket {
private NoSSLv3SSLSocket(SSLSocket delegate) {
super(delegate);
}
@Override
public void setEnabledProtocols(String[] protocols) {
if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) {
List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getEnabledProtocols()));
if (enabledProtocols.size() > 1) {
enabledProtocols.remove("SSLv3");
System.out.println("Removed SSLv3 from enabled protocols");
} else {
System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols));
}
protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]);
}
super.setEnabledProtocols(new String[]{"TLSv1.2","TLSv1.1","TLSv1"});
}
}
public class DelegateSSLSocket extends SSLSocket {
protected final SSLSocket delegate;
DelegateSSLSocket(SSLSocket delegate) {
this.delegate = delegate;
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override
public String[] getEnabledCipherSuites() {
return delegate.getEnabledCipherSuites();
}
@Override
public void setEnabledCipherSuites(String[] suites) {
delegate.setEnabledCipherSuites(suites);
}
@Override
public String[] getSupportedProtocols() {
return delegate.getSupportedProtocols();
}
@Override
public String[] getEnabledProtocols() {
return delegate.getEnabledProtocols();
}
@Override
public void setEnabledProtocols(String[] protocols) {
delegate.setEnabledProtocols(protocols);
}
@Override
public SSLSession getSession() {
return delegate.getSession();
}
@Override
public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
delegate.addHandshakeCompletedListener(listener);
}
@Override
public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
delegate.removeHandshakeCompletedListener(listener);
}
@Override
public void startHandshake() throws IOException {
delegate.startHandshake();
}
@Override
public void setUseClientMode(boolean mode) {
delegate.setUseClientMode(mode);
}
@Override
public boolean getUseClientMode() {
return delegate.getUseClientMode();
}
@Override
public void setNeedClientAuth(boolean need) {
delegate.setNeedClientAuth(need);
}
@Override
public void setWantClientAuth(boolean want) {
delegate.setWantClientAuth(want);
}
@Override
public boolean getNeedClientAuth() {
return delegate.getNeedClientAuth();
}
@Override
public boolean getWantClientAuth() {
return delegate.getWantClientAuth();
}
@Override
public void setEnableSessionCreation(boolean flag) {
delegate.setEnableSessionCreation(flag);
}
@Override
public boolean getEnableSessionCreation() {
return delegate.getEnableSessionCreation();
}
@Override
public void bind(SocketAddress localAddr) throws IOException {
delegate.bind(localAddr);
}
@Override
public synchronized void close() throws IOException {
delegate.close();
}
@Override
public void connect(SocketAddress remoteAddr) throws IOException {
delegate.connect(remoteAddr);
}
@Override
public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
delegate.connect(remoteAddr, timeout);
}
@Override
public SocketChannel getChannel() {
return delegate.getChannel();
}
@Override
public InetAddress getInetAddress() {
return delegate.getInetAddress();
}
@Override
public InputStream getInputStream() throws IOException {
return delegate.getInputStream();
}
@Override
public boolean getKeepAlive() throws SocketException {
return delegate.getKeepAlive();
}
@Override
public InetAddress getLocalAddress() {
return delegate.getLocalAddress();
}
@Override
public int getLocalPort() {
return delegate.getLocalPort();
}
@Override
public SocketAddress getLocalSocketAddress() {
return delegate.getLocalSocketAddress();
}
@Override
public boolean getOOBInline() throws SocketException {
return delegate.getOOBInline();
}
@Override
public OutputStream getOutputStream() throws IOException {
return delegate.getOutputStream();
}
@Override
public int getPort() {
return delegate.getPort();
}
@Override
public synchronized int getReceiveBufferSize() throws SocketException {
return delegate.getReceiveBufferSize();
}
@Override
public SocketAddress getRemoteSocketAddress() {
return delegate.getRemoteSocketAddress();
}
@Override
public boolean getReuseAddress() throws SocketException {
return delegate.getReuseAddress();
}
@Override
public synchronized int getSendBufferSize() throws SocketException {
return delegate.getSendBufferSize();
}
@Override
public int getSoLinger() throws SocketException {
return delegate.getSoLinger();
}
@Override
public synchronized int getSoTimeout() throws SocketException {
return delegate.getSoTimeout();
}
@Override
public boolean getTcpNoDelay() throws SocketException {
return delegate.getTcpNoDelay();
}
@Override
public int getTrafficClass() throws SocketException {
return delegate.getTrafficClass();
}
@Override
public boolean isBound() {
return delegate.isBound();
}
@Override
public boolean isClosed() {
return delegate.isClosed();
}
@Override
public boolean isConnected() {
return delegate.isConnected();
}
@Override
public boolean isInputShutdown() {
return delegate.isInputShutdown();
}
@Override
public boolean isOutputShutdown() {
return delegate.isOutputShutdown();
}
@Override
public void sendUrgentData(int value) throws IOException {
delegate.sendUrgentData(value);
}
@Override
public void setKeepAlive(boolean keepAlive) throws SocketException {
delegate.setKeepAlive(keepAlive);
}
@Override
public void setOOBInline(boolean oobinline) throws SocketException {
delegate.setOOBInline(oobinline);
}
@Override
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
delegate.setPerformancePreferences(connectionTime, latency, bandwidth);
}
@Override
public synchronized void setReceiveBufferSize(int size) throws SocketException {
delegate.setReceiveBufferSize(size);
}
@Override
public void setReuseAddress(boolean reuse) throws SocketException {
delegate.setReuseAddress(reuse);
}
@Override
public synchronized void setSendBufferSize(int size) throws SocketException {
delegate.setSendBufferSize(size);
}
@Override
public void setSoLinger(boolean on, int timeout) throws SocketException {
delegate.setSoLinger(on, timeout);
}
@Override
public synchronized void setSoTimeout(int timeout) throws SocketException {
delegate.setSoTimeout(timeout);
}
@Override
public void setTcpNoDelay(boolean on) throws SocketException {
delegate.setTcpNoDelay(on);
}
@Override
public void setTrafficClass(int value) throws SocketException {
delegate.setTrafficClass(value);
}
@Override
public void shutdownInput() throws IOException {
delegate.shutdownInput();
}
@Override
public void shutdownOutput() throws IOException {
delegate.shutdownOutput();
}
@Override
public String toString() {
return delegate.toString();
}
@Override
public boolean equals(Object o) {
return delegate.equals(o);
}
}
}
package com.hls.plugins.barcode.Util;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**
* Created by panx on 2017/3/15.
*/
public class Util {
public static boolean isNetworkAvailable(Context context){
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if(networkInfo!=null&&networkInfo.isAvailable()){
return true;
}
return false;
}
}
package com.zbar.lib;
public class ZbarManager {
static {
System.loadLibrary("zbar");
}
public native String decode(byte[] data, int width, int height, boolean isCrop, int x, int y, int cwidth, int cheight);
}
package com.hls.plugins.barcode.activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import __ANDROID_PACKAGE__.R;
/**
* Created by panx on 2017/3/17.
*/
public class DialogToast extends Dialog {
public DialogToast(Context context) {
super(context);
}
protected DialogToast(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
public DialogToast(Context context, int themeResId) {
super(context, themeResId);
}
public static class Builder {
private Context context;
private String msg;
private OnClickListener onClickListener;
public Builder(Context context) {
this.context = context;
}
public Builder setMsg(String msg){
this.msg = msg;
return this;
}
public Builder setOnClickListener(OnClickListener onClickListener){
this.onClickListener = onClickListener;
return this;
}
public DialogToast create(){
LayoutInflater inflater = LayoutInflater.from(context);
final DialogToast dialogToast = new DialogToast(context,R.style.Custom_Progress);
View view = inflater.inflate(R.layout.dialog_cancel_layout,null);
dialogToast.setContentView(view);
TextView txtMsg =(TextView) view.findViewById(R.id.txt_msg);
ImageView imgCancel = (ImageView) view.findViewById(R.id.txt_cancel);
if(msg!=null){
txtMsg.setText(msg);
}
imgCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onClickListener.onClick(dialogToast, DialogInterface.BUTTON_NEGATIVE);
}
});
WindowManager.LayoutParams lp = dialogToast.getWindow().getAttributes();
// 设置背景层透明度
lp.dimAmount = 0.0f;
dialogToast.getWindow().setAttributes(lp);
dialogToast.setCancelable(false);
return dialogToast;
}
}
}
package com.hls.plugins.barcode.activity;
/**
* Created by panx on 2017/3/16.
*/
public interface IUnOpenWebActivity {
void stillUnOpen();
void hasOpen();
void ToastCenter(String msg);
void showProgressDialog(boolean flag);
void goNetworkErrorPage();
}
package com.hls.plugins.barcode.activity;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import __ANDROID_PACKAGE__.R;
import com.hls.plugins.barcode.bean.ArgsBean;
/**
* Created by panx on 2017/3/15.
*/
public class NetWorkErrorActivity extends Activity implements View.OnClickListener{
private ArgsBean argsBean;
private TextView txtTipNetworkError;
private TextView txtTip1;
private TextView txtTip2;
private ImageView imgBtnBack;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_network_error);
readIntent();
initView();
initListener();
initData();
}
private void readIntent(){
argsBean = getIntent().getParcelableExtra("ARGS");
}
private void initView(){
txtTipNetworkError = (TextView)findViewById(R.id.txt_tipNetworkError);
txtTip1 = (TextView)findViewById(R.id.txt_tip1);
txtTip2 = (TextView)findViewById(R.id.txt_tip2);
imgBtnBack = (ImageView) findViewById(R.id.imgBtnBack);
}
private void initListener(){
imgBtnBack.setOnClickListener(this);
}
private void initData(){
txtTipNetworkError.setText(argsBean.getPageInfoBean().getTipNetworkError());
txtTip1.setText(argsBean.getPageInfoBean().getFooterFirst());
txtTip2.setText(argsBean.getPageInfoBean().getFooterSecond());
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id){
case R.id.imgBtnBack:{
onBackPressed();
break;
}default:
break;
}
}
}
package com.hls.plugins.barcode.activity;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import __ANDROID_PACKAGE__.R;
import com.hls.plugins.barcode.Util.Util;
import com.hls.plugins.barcode.bean.ArgsBean;
/**
* Created by panx on 2017/3/15.
*/
public class UnOpenWebActivity extends Activity implements View.OnClickListener,IUnOpenWebActivity {
private ImageView imgBtnBack;
private TextView txtTipOffline;
private TextView txtOpen;
private TextView txtTip1;
private TextView txtTip2;
private TextView scanTitile;
private ArgsBean argsBean;
private DialogToast dialogToast;
private UnOpenWebActivityPresenter unOpenWebActivityPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_unopen_web);
unOpenWebActivityPresenter = new UnOpenWebActivityPresenter(this,this);
readIntent();
initView();
initData();
initListener();
}
private void readIntent() {
argsBean = getIntent().getParcelableExtra("ARGS");
}
private void initView() {
txtTipOffline = (TextView) findViewById(R.id.txt_tipOffLine);
txtOpen = (TextView) findViewById(R.id.txt_open);
txtTip1 = (TextView) findViewById(R.id.txt_tip1);
txtTip2 = (TextView) findViewById(R.id.txt_tip2);
imgBtnBack = (ImageView) findViewById(R.id.imgBtnBack);
scanTitile=(TextView) findViewById(R.id.scanTitile);
}
private void initData() {
txtTipOffline.setText(argsBean.getPageInfoBean().getTipOffline());
txtOpen.setText(argsBean.getPageInfoBean().getOpenButton());
txtTip1.setText(argsBean.getPageInfoBean().getFooterFirst());
txtTip2.setText(argsBean.getPageInfoBean().getFooterSecond());
scanTitile.setText(argsBean.getPageInfoBean().getBarTitle());
}
private void initListener(){
txtOpen.setOnClickListener(this);
imgBtnBack.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id){
case R.id.imgBtnBack:
onBackPressed();
break;
case R.id.txt_open:
unOpenWebActivityPresenter.toValidation(argsBean);
break;
default:
break;
}
}
/**
* 扔未打开
*/
@Override
public void stillUnOpen(){
ToastCenter(argsBean.getPageInfoBean().getTipOffline());
}
@Override
public void hasOpen(){
onBackPressed();
}
@Override
public void ToastCenter(String msg) {
Toast toast = Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
@Override
public void showProgressDialog(boolean isShow) {
if(dialogToast == null&&isShow){
DialogToast.Builder builder = new DialogToast.Builder(this);
dialogToast = builder.setMsg(argsBean.getPageInfoBean().getTipLoading())
.setOnClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
}).create();
dialogToast.show();
}else if(isShow){
dialogToast.show();
}else if(!isShow&&dialogToast!=null){
dialogToast.dismiss();
}
}
@Override
public void goNetworkErrorPage() {
Intent intent = new Intent(this, NetWorkErrorActivity.class);
intent.putExtra("ARGS",argsBean);
startActivity(intent);
}
}
package com.hls.plugins.barcode.activity;
import android.content.Context;
import com.hls.plugins.barcode.Util.Util;
import com.hls.plugins.barcode.bean.ArgsBean;
import com.hls.plugins.barcode.http.HttpManager;
import com.hls.plugins.barcode.http.ResultCallback;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by panx on 2017/3/16.
*/
public class UnOpenWebActivityPresenter {
private IUnOpenWebActivity iUnOpenWebActivity;
private Context context;
public UnOpenWebActivityPresenter(IUnOpenWebActivity iUnOpenWebActivity,Context context) {
this.iUnOpenWebActivity = iUnOpenWebActivity;
this.context = context;
}
public void toValidation(ArgsBean argsBean){
iUnOpenWebActivity.showProgressDialog(true);
HttpManager.get(argsBean.getHttpInfos().get(1), new ResultCallback<String>() {
@Override
public void onError(Exception e, String error) {
iUnOpenWebActivity.showProgressDialog(false);
if(!Util.isNetworkAvailable(context)){
iUnOpenWebActivity.goNetworkErrorPage();
}else{
iUnOpenWebActivity.ToastCenter(error);
}
}
@Override
public void onResponse(String response, String result) {
iUnOpenWebActivity.showProgressDialog(false);
doResultBiz(response);
}
});
}
private void doResultBiz(String response){
try {
JSONObject object = new JSONObject(response);
int online = object.getInt("online");
if(online!=1){
iUnOpenWebActivity.stillUnOpen();
}else{
iUnOpenWebActivity.hasOpen();
}
} catch (JSONException e) {
iUnOpenWebActivity.ToastCenter(HttpManager.NETWORK_ERROR);
e.printStackTrace();
}
}
}
package com.hls.plugins.barcode.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
/**
* Created by panx on 2017/3/15.
*/
public class ArgsBean implements Parcelable {
public final static String REVIEW = "REVIEW";
public final static String AUDIT = "AUDIT";
public final static String BACK = "BACK";
public final static String AUDIT_PASS = "AUDIT_PASS";
public final static String RECEIVE ="RECEIVE";
public final static String SCAN ="SCAN";
public final static String INVOICE = "INVOICE";
private PageInfoBean pageInfoBean;
private String operateMethod;
private ArrayList<HttpInfoBean> httpInfos;
public ArgsBean() {
}
protected ArgsBean(Parcel in) {
pageInfoBean = in.readParcelable(PageInfoBean.class.getClassLoader());
operateMethod = in.readString();
httpInfos = in.createTypedArrayList(HttpInfoBean.CREATOR);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(pageInfoBean, flags);
dest.writeString(operateMethod);
dest.writeTypedList(httpInfos);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<ArgsBean> CREATOR = new Creator<ArgsBean>() {
@Override
public ArgsBean createFromParcel(Parcel in) {
return new ArgsBean(in);
}
@Override
public ArgsBean[] newArray(int size) {
return new ArgsBean[size];
}
};
public PageInfoBean getPageInfoBean() {
return pageInfoBean;
}
public void setPageInfoBean(PageInfoBean pageInfoBean) {
this.pageInfoBean = pageInfoBean;
}
public String getOperateMethod() {
return operateMethod;
}
public void setOperateMethod(String operateMethod) {
this.operateMethod = operateMethod;
}
public ArrayList<HttpInfoBean> getHttpInfos() {
return httpInfos;
}
public void setHttpInfos(ArrayList<HttpInfoBean> httpInfos) {
this.httpInfos = httpInfos;
}
}
package com.hls.plugins.barcode.bean;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
/**
* Created by panx on 2017/3/15.
*/
public class ArgsBiz {
private final static String TAG = "ArgsBiz";
public ArgsBean getArgsBeanByJSONObject(JSONObject object) {
ArgsBean argsBean = new ArgsBean();
try {
JSONObject pageObject = object.getJSONObject("message");
argsBean.setPageInfoBean(getPageInfoBeanByJsonObject(pageObject));
String operateMethod = object.optString("operationType", "");
argsBean.setOperateMethod(operateMethod);
JSONArray httpArray = object.optJSONArray("requests");
argsBean.setHttpInfos(getHttpInfosByJsonArray(httpArray));
} catch (JSONException e) {
e.printStackTrace();
return null;
}
return argsBean;
}
private PageInfoBean getPageInfoBeanByJsonObject(JSONObject object) {
PageInfoBean pageInfoBean = new PageInfoBean();
pageInfoBean.setTitle(object.optString("title", ""));
pageInfoBean.setTipScan(object.optString("tipScan", ""));
pageInfoBean.setTipInput(object.optString("tipInput", ""));
pageInfoBean.setTipLoading(object.optString("tipLoading", ""));
pageInfoBean.setTipNetworkError(object.optString("tipNetworkError", ""));
pageInfoBean.setTipOffline(object.optString("tipOffline", ""));
pageInfoBean.setOpenButton(object.optString("openButton", ""));
pageInfoBean.setFooterFirst(object.optString("footerFirst", ""));
pageInfoBean.setFooterSecond(object.optString("footerSecond", ""));
pageInfoBean.setBarTitle(object.optString("barTitle", ""));
pageInfoBean.setExplainFlag(object.optBoolean("explainFlag", false));
pageInfoBean.setInputFlag(object.optBoolean("inputFlag", true));
pageInfoBean.setLightFlag(object.optBoolean("lightFlag", true));
pageInfoBean.setTipLightOff(object.optString("tipLightOff", ""));
pageInfoBean.setTipLightOn(object.optString("tipLightOn", ""));
pageInfoBean.setDelayTime(object.optLong("delayTime"));
return pageInfoBean;
}
private ArrayList<HttpInfoBean> getHttpInfosByJsonArray(JSONArray array) {
if (array == null) return null;
ArrayList<HttpInfoBean> httpInfos = new ArrayList<HttpInfoBean>();
try {
for (int i = 0; i < array.length(); i++) {
HttpInfoBean httpInfoBean = getHttpInfoBeanByJsonObject(array.getJSONObject(i));
httpInfos.add(httpInfoBean);
}
} catch (JSONException e) {
e.printStackTrace();
Log.e(TAG, "wrong arguments http infos");
return null;
}
return httpInfos;
}
private HttpInfoBean getHttpInfoBeanByJsonObject(JSONObject object) {
HttpInfoBean httpInfoBean = new HttpInfoBean();
HttpInfoBean.Config config = new HttpInfoBean.Config();
HttpInfoBean.Headers headers = new HttpInfoBean.Headers();
try {
httpInfoBean.setUrl(object.getString("url"));
httpInfoBean.setMethod(object.getString("method"));
JSONObject headerObject = object.getJSONObject("headers");
JSONObject configObject = object.getJSONObject("config");
JSONObject dataObject = object.optJSONObject("data");
if (dataObject == null) {
dataObject = new JSONObject();
}
headers.setAuthorization(headerObject.getString("Authorization"));
headers.setContentType(headerObject.getString("Content-Type"));
config.setTimeout(configObject.getInt("timeout"));
httpInfoBean.setConfig(config);
httpInfoBean.setData(dataObject.toString());
httpInfoBean.setHeaders(headers);
} catch (JSONException e) {
e.printStackTrace();
Log.e(TAG, "wrong arguments http info");
return null;
}
return httpInfoBean;
}
}
package com.hls.plugins.barcode.bean;
/**
* Created by panx on 2017/3/9.
*/
public class CodeInfoBean {
public final static String SUCCESS = "0000";
public final static String CODE = "code";
public final static String MSG = "msg";
public final static String ONLINE = "online";
public final static String EXPENSE_REPORT = "expenseReport";
private String code;
private String msg;
private String online;
private String expenseReport;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getOnline() {
return online;
}
public void setOnline(String online) {
this.online = online;
}
public String getExpenseReport() {
return expenseReport;
}
public void setExpenseReport(String expenseReport) {
this.expenseReport = expenseReport;
}
}
package com.hls.plugins.barcode.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by panx on 2017/3/15.
*/
public class HttpInfoBean implements Parcelable{
private String url;
private String method;
private Headers headers;
private String data;
private Config config;
public HttpInfoBean() {
}
/**
* 请求头
*/
public static class Headers implements Parcelable {
private String authorization;
private String contentType;
public Headers() {
}
protected Headers(Parcel in) {
authorization = in.readString();
contentType = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(authorization);
dest.writeString(contentType);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Headers> CREATOR = new Creator<Headers>() {
@Override
public Headers createFromParcel(Parcel in) {
return new Headers(in);
}
@Override
public Headers[] newArray(int size) {
return new Headers[size];
}
};
public String getAuthorization() {
return authorization;
}
public void setAuthorization(String authorization) {
this.authorization = authorization;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
}
/**
* 配置
*/
public static class Config implements Parcelable {
private int timeout;
public Config() {
}
protected Config(Parcel in) {
timeout = in.readInt();
}
public static final Creator<Config> CREATOR = new Creator<Config>() {
@Override
public Config createFromParcel(Parcel in) {
return new Config(in);
}
@Override
public Config[] newArray(int size) {
return new Config[size];
}
};
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(timeout);
}
}
protected HttpInfoBean(Parcel in) {
url = in.readString();
method = in.readString();
headers = in.readParcelable(Headers.class.getClassLoader());
data = in.readString();
config = in.readParcelable(Config.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(url);
dest.writeString(method);
dest.writeParcelable(headers, flags);
dest.writeString(data);
dest.writeParcelable(config, flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<HttpInfoBean> CREATOR = new Creator<HttpInfoBean>() {
@Override
public HttpInfoBean createFromParcel(Parcel in) {
return new HttpInfoBean(in);
}
@Override
public HttpInfoBean[] newArray(int size) {
return new HttpInfoBean[size];
}
};
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Config getConfig() {
return config;
}
public void setConfig(Config config) {
this.config = config;
}
public Headers getHeaders() {
return headers;
}
public void setHeaders(Headers headers) {
this.headers = headers;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
package com.hls.plugins.barcode.bean;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by panx on 2017/3/15.
*/
public class PageInfoBean implements Parcelable {
private final static String TAG = "PageInfoBean";
private String title;
private String tipScan;
private String tipInput;
private String tipLoading;
private String tipNetworkError;
private String tipOffline;
private String openButton;
private String footerFirst;
private String footerSecond;
private String barTitle;
private boolean explainFlag;
private boolean inputFlag;
private boolean lightFlag;
private String tipLightOn;
private String tipLightOff;
private long delayTime;
public PageInfoBean() {
}
protected PageInfoBean(Parcel in) {
title = in.readString();
tipScan = in.readString();
tipInput = in.readString();
tipLoading = in.readString();
tipNetworkError = in.readString();
tipOffline = in.readString();
openButton = in.readString();
footerFirst = in.readString();
footerSecond = in.readString();
barTitle = in.readString();
explainFlag = in.readByte() != 0;
inputFlag = in.readByte() != 0;
lightFlag = in.readByte() != 0;
tipLightOn = in.readString();
tipLightOff = in.readString();
delayTime = in.readLong();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(tipScan);
dest.writeString(tipInput);
dest.writeString(tipLoading);
dest.writeString(tipNetworkError);
dest.writeString(tipOffline);
dest.writeString(openButton);
dest.writeString(footerFirst);
dest.writeString(footerSecond);
dest.writeString(barTitle);
dest.writeByte((byte) (explainFlag ? 1 : 0));
dest.writeByte((byte) (inputFlag ? 1 : 0));
dest.writeByte((byte) (lightFlag ? 1 : 0));
dest.writeString(tipLightOn);
dest.writeString(tipLightOff);
dest.writeLong(delayTime);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<PageInfoBean> CREATOR = new Creator<PageInfoBean>() {
@Override
public PageInfoBean createFromParcel(Parcel in) {
return new PageInfoBean(in);
}
@Override
public PageInfoBean[] newArray(int size) {
return new PageInfoBean[size];
}
};
public static String getTAG() {
return TAG;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getTipScan() {
return tipScan;
}
public void setTipScan(String tipScan) {
this.tipScan = tipScan;
}
public String getTipInput() {
return tipInput;
}
public void setTipInput(String tipInput) {
this.tipInput = tipInput;
}
public String getTipLoading() {
return tipLoading;
}
public void setTipLoading(String tipLoading) {
this.tipLoading = tipLoading;
}
public String getTipNetworkError() {
return tipNetworkError;
}
public void setTipNetworkError(String tipNetworkError) {
this.tipNetworkError = tipNetworkError;
}
public String getTipOffline() {
return tipOffline;
}
public void setTipOffline(String tipOffline) {
this.tipOffline = tipOffline;
}
public String getOpenButton() {
return openButton;
}
public void setOpenButton(String openButton) {
this.openButton = openButton;
}
public String getFooterFirst() {
return footerFirst;
}
public void setFooterFirst(String footerFirst) {
this.footerFirst = footerFirst;
}
public String getFooterSecond() {
return footerSecond;
}
public void setFooterSecond(String footerSecond) {
this.footerSecond = footerSecond;
}
public String getBarTitle() {
return barTitle;
}
public void setBarTitle(String barTitle) {
this.barTitle = barTitle;
}
public boolean isExplainFlag() {
return explainFlag;
}
public void setExplainFlag(boolean explainFlag) {
this.explainFlag = explainFlag;
}
public boolean isInputFlag() {
return inputFlag;
}
public void setInputFlag(boolean inputFlag) {
this.inputFlag = inputFlag;
}
public boolean isLightFlag() {
return lightFlag;
}
public void setLightFlag(boolean lightFlag) {
this.lightFlag = lightFlag;
}
public String getTipLightOn() {
return tipLightOn;
}
public void setTipLightOn(String tipLightOn) {
this.tipLightOn = tipLightOn;
}
public String getTipLightOff() {
return tipLightOff;
}
public void setTipLightOff(String tipLightOff) {
this.tipLightOff = tipLightOff;
}
public long getDelayTime() {
return delayTime;
}
public void setDelayTime(long delayTime) {
this.delayTime = delayTime;
}
public static Creator<PageInfoBean> getCREATOR() {
return CREATOR;
}
}
package com.hls.plugins.barcode.camera;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
final class AutoFocusCallback implements Camera.AutoFocusCallback {
private static final String TAG = AutoFocusCallback.class.getSimpleName();
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);
autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
autoFocusHandler = null;
} else {
Log.d(TAG, "Got auto-focus callback, but no handler for it");
}
}
}
package com.hls.plugins.barcode.camera;
import java.util.regex.Pattern;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
final class CameraConfigurationManager {
private static final String TAG = CameraConfigurationManager.class
.getSimpleName();
private static final int TEN_DESIRED_ZOOM = 27;
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
private final Context context;
private Point screenResolution;
private Point cameraResolution;
private int previewFormat;
private String previewFormatString;
CameraConfigurationManager(Context context) {
this.context = context;
}
@SuppressWarnings("deprecation")
void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
previewFormat = parameters.getPreviewFormat();
previewFormatString = parameters.get("preview-format");
WindowManager manager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
screenResolution = new Point(display.getWidth(), display.getHeight());
Point screenResolutionForCamera = new Point();
screenResolutionForCamera.x = screenResolution.x;
screenResolutionForCamera.y = screenResolution.y;
if (screenResolution.x < screenResolution.y) {
screenResolutionForCamera.x = screenResolution.y;
screenResolutionForCamera.y = screenResolution.x;
}
cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);
}
void setDesiredCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
setFlash(parameters);
setZoom(parameters);
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
Point getCameraResolution() {
return cameraResolution;
}
Point getScreenResolution() {
return screenResolution;
}
int getPreviewFormat() {
return previewFormat;
}
String getPreviewFormatString() {
return previewFormatString;
}
private static Point getCameraResolution(Camera.Parameters parameters,
Point screenResolution) {
String previewSizeValueString = parameters.get("preview-size-values");
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
Point cameraResolution = null;
if (previewSizeValueString != null) {
cameraResolution = findBestPreviewSizeValue(previewSizeValueString,
screenResolution);
}
if (cameraResolution == null) {
cameraResolution = new Point((screenResolution.x >> 3) << 3,
(screenResolution.y >> 3) << 3);
}
return cameraResolution;
}
private static Point findBestPreviewSizeValue(
CharSequence previewSizeValueString, Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
previewSize = previewSize.trim();
int dimPosition = previewSize.indexOf('x');
if (dimPosition < 0) {
continue;
}
int newX;
int newY;
try {
newX = Integer.parseInt(previewSize.substring(0, dimPosition));
newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
} catch (NumberFormatException nfe) {
continue;
}
int newDiff = Math.abs(newX - screenResolution.x)
+ Math.abs(newY - screenResolution.y);
if (newDiff == 0) {
bestX = newX;
bestY = newY;
break;
} else if (newDiff < diff) {
bestX = newX;
bestY = newY;
diff = newDiff;
}
}
if (bestX > 0 && bestY > 0) {
return new Point(bestX, bestY);
}
return null;
}
private static int findBestMotZoomValue(CharSequence stringValues,
int tenDesiredZoom) {
int tenBestValue = 0;
for (String stringValue : COMMA_PATTERN.split(stringValues)) {
stringValue = stringValue.trim();
double value;
try {
value = Double.parseDouble(stringValue);
} catch (NumberFormatException nfe) {
return tenDesiredZoom;
}
int tenValue = (int) (10.0 * value);
if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom
- tenBestValue)) {
tenBestValue = tenValue;
}
}
return tenBestValue;
}
private void setFlash(Camera.Parameters parameters) {
if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3
parameters.set("flash-value", 1);
} else {
parameters.set("flash-value", 2);
}
parameters.set("flash-mode", "off");
}
private void setZoom(Camera.Parameters parameters) {
String zoomSupportedString = parameters.get("zoom-supported");
if (zoomSupportedString != null
&& !Boolean.parseBoolean(zoomSupportedString)) {
return;
}
int tenDesiredZoom = TEN_DESIRED_ZOOM;
String maxZoomString = parameters.get("max-zoom");
if (maxZoomString != null) {
try {
int tenMaxZoom = (int) (10.0 * Double
.parseDouble(maxZoomString));
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad max-zoom: " + maxZoomString);
}
}
String takingPictureZoomMaxString = parameters
.get("taking-picture-zoom-max");
if (takingPictureZoomMaxString != null) {
try {
int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad taking-picture-zoom-max: "
+ takingPictureZoomMaxString);
}
}
String motZoomValuesString = parameters.get("mot-zoom-values");
if (motZoomValuesString != null) {
tenDesiredZoom = findBestMotZoomValue(motZoomValuesString,
tenDesiredZoom);
}
String motZoomStepString = parameters.get("mot-zoom-step");
if (motZoomStepString != null) {
try {
double motZoomStep = Double.parseDouble(motZoomStepString
.trim());
int tenZoomStep = (int) (10.0 * motZoomStep);
if (tenZoomStep > 1) {
tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
}
} catch (NumberFormatException nfe) {
// continue
}
}
// Set zoom. This helps encourage the user to pull back.
// Some devices like the Behold have a zoom parameter
if (maxZoomString != null || motZoomValuesString != null) {
parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
}
// Most devices, like the Hero, appear to expose this zoom parameter.
// It takes on values like "27" which appears to mean 2.7x zoom
if (takingPictureZoomMaxString != null) {
parameters.set("taking-picture-zoom", tenDesiredZoom);
}
}
}
package com.hls.plugins.barcode.camera;
import java.io.IOException;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.os.Handler;
import android.view.SurfaceHolder;
public final class CameraManager {
private static CameraManager cameraManager;
static final int SDK_INT;
static {
int sdkInt;
try {
sdkInt = android.os.Build.VERSION.SDK_INT;
} catch (NumberFormatException nfe) {
sdkInt = 10000;
}
SDK_INT = sdkInt;
}
private final CameraConfigurationManager configManager;
private Camera camera;
private boolean initialized;
private boolean previewing;
private final boolean useOneShotPreviewCallback;
private final PreviewCallback previewCallback;
private final AutoFocusCallback autoFocusCallback;
private Parameters parameter;
public static void init(Context context) {
if (cameraManager == null) {
cameraManager = new CameraManager(context);
}
}
public static CameraManager get() {
return cameraManager;
}
private CameraManager(Context context) {
this.configManager = new CameraConfigurationManager(context);
useOneShotPreviewCallback = SDK_INT > 3;
previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);
autoFocusCallback = new AutoFocusCallback();
}
public void openDriver(SurfaceHolder holder) throws IOException {
if (camera == null) {
camera = Camera.open();
if (camera == null) {
throw new IOException();
}
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(camera);
}
configManager.setDesiredCameraParameters(camera);
FlashlightManager.enableFlashlight();
}
}
public Point getCameraResolution() {
return configManager.getCameraResolution();
}
public void closeDriver() {
if (camera != null) {
FlashlightManager.disableFlashlight();
camera.release();
camera = null;
}
}
public void startPreview() {
if (camera != null && !previewing) {
camera.startPreview();
previewing = true;
}
}
public void stopPreview() {
if (camera != null && previewing) {
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
camera.stopPreview();
previewCallback.setHandler(null, 0);
autoFocusCallback.setHandler(null, 0);
previewing = false;
}
}
public void requestPreviewFrame(Handler handler, int message) {
if (camera != null && previewing) {
previewCallback.setHandler(handler, message);
if (useOneShotPreviewCallback) {
camera.setOneShotPreviewCallback(previewCallback);
} else {
camera.setPreviewCallback(previewCallback);
}
}
}
public void requestAutoFocus(Handler handler, int message) {
if (camera != null && previewing) {
autoFocusCallback.setHandler(handler, message);
camera.autoFocus(autoFocusCallback);
}
}
public void openLight() {
if (camera != null) {
parameter = camera.getParameters();
parameter.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameter);
}
}
public void offLight() {
if (camera != null) {
parameter = camera.getParameters();
parameter.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameter);
}
}
}
package com.hls.plugins.barcode.camera;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.os.IBinder;
import android.util.Log;
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);
}
}
}
package com.hls.plugins.barcode.camera;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
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");
}
}
}
package com.hls.plugins.barcode.decode;
import android.os.Handler;
import android.os.Message;
import __ANDROID_PACKAGE__.R;
import com.hls.plugins.barcode.CaptureActivity;
import com.hls.plugins.barcode.camera.CameraManager;
public final class CaptureActivityHandler extends Handler {
DecodeThread decodeThread = null;
CaptureActivity activity = null;
private State state;
private enum State {
PREVIEW, SUCCESS, DONE
}
public CaptureActivityHandler(CaptureActivity activity) {
this.activity = activity;
decodeThread = new DecodeThread(activity);
decodeThread.start();
state = State.SUCCESS;
CameraManager.get().startPreview();
restartPreviewAndDecode();
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
case R.id.auto_focus:
if (state == State.PREVIEW) {
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
}
break;
case R.id.restart_preview:
restartPreviewAndDecode();
break;
case R.id.decode_succeeded:
state = State.SUCCESS;
activity.handleDecode((String) message.obj);// 解析成功,回调
break;
case R.id.decode_failed:
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(),
R.id.decode);
break;
}
}
public void quitSynchronously() {
state = State.DONE;
CameraManager.get().stopPreview();
removeMessages(R.id.decode_succeeded);
removeMessages(R.id.decode_failed);
removeMessages(R.id.decode);
removeMessages(R.id.auto_focus);
}
private void restartPreviewAndDecode() {
if (state == State.SUCCESS) {
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(),
R.id.decode);
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
}
}
}
package com.hls.plugins.barcode.decode;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import __ANDROID_PACKAGE__.R;
import com.hls.plugins.barcode.CaptureActivity;
import com.zbar.lib.ZbarManager;
final class DecodeHandler extends Handler {
CaptureActivity activity = null;
DecodeHandler(CaptureActivity activity) {
this.activity = activity;
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
case R.id.decode:
decode((byte[]) message.obj, message.arg1, message.arg2);
break;
case R.id.quit:
Looper.myLooper().quit();
break;
}
}
private void decode(byte[] data, int width, int height) {
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];
}
int tmp = width;// Here we are swapping, that's the difference to #11
width = height;
height = tmp;
ZbarManager manager = new ZbarManager();
String result = manager.decode(rotatedData, width, height, true,
activity.getX(), activity.getY(), activity.getCropWidth(),
activity.getCropHeight());
if (result != null) {
if(null != activity.getHandler()){
Message msg = new Message();
msg.obj = result;
msg.what = R.id.decode_succeeded;
activity.getHandler().sendMessage(msg);
}
} else {
if (null != activity.getHandler()) {
activity.getHandler().sendEmptyMessage(R.id.decode_failed);
}
}
}
}
package com.hls.plugins.barcode.decode;
import java.util.concurrent.CountDownLatch;
import com.hls.plugins.barcode.CaptureActivity;
import android.os.Handler;
import android.os.Looper;
final class DecodeThread extends Thread {
CaptureActivity activity;
private Handler handler;
private final CountDownLatch handlerInitLatch;
DecodeThread(CaptureActivity activity) {
this.activity = activity;
handlerInitLatch = new CountDownLatch(1);
}
Handler getHandler() {
try {
handlerInitLatch.await();
} catch (InterruptedException ie) {
// continue?
}
return handler;
}
@Override
public void run() {
Looper.prepare();
handler = new DecodeHandler(activity);
handlerInitLatch.countDown();
Looper.loop();
}
}
package com.hls.plugins.barcode.decode;
import android.app.Activity;
import android.content.DialogInterface;
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();
}
}
package com.hls.plugins.barcode.decode;
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;
import android.app.Activity;
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;
}
}
}
package com.hls.plugins.barcode.http;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.hls.plugins.barcode.bean.ArgsBean;
import com.hls.plugins.barcode.bean.CodeInfoBean;
import com.hls.plugins.barcode.bean.HttpInfoBean;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by panx on 2017/3/8.
*/
public class HttpManager {
public static final String TAG = "HttpManager";
public static final String NETWORK_ERROR = "请求发生错误,请稍后再试!";
public static Handler handler = new Handler(Looper.getMainLooper());
public static void get(final HttpInfoBean httpInfoBean, final ResultCallback<String> callback){
new Thread(){
@Override
public void run() {
super.run();
doGet(httpInfoBean,callback);
}
}.start();
}
private static void doGet(HttpInfoBean httpInfoBean, final ResultCallback<String> callback){
HttpUtil.get(httpInfoBean, new ResultCallback<String>() {
@Override
public void onError(Exception e, String error) {
handlerError(e,callback);
}
@Override
public void onResponse(String response, String result) {
handlerSuccess(response,callback);
}
});
}
public static void post(final HttpInfoBean httpInfoBean, final ResultCallback<String> callback) {
new Thread() {
@Override
public void run() {
super.run();
doPost(httpInfoBean, callback);
}
}.start();
}
private static void doPost(HttpInfoBean httpInfoBean, final ResultCallback<String> callback) {
HttpUtil.post(httpInfoBean, new ResultCallback<String>() {
@Override
public void onError(Exception e, String error) {
handlerError(e, callback);
}
@Override
public void onResponse(String response,String result) {
handlerSuccess(response, callback);
}
});
}
/**
* 网络请求成功时的处理
* @param response
* @param callback
*/
private static void handlerSuccess(final String response, final ResultCallback callback) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onResponse(response,"");
}
});
}
/**
* 网络请求失败的处理
* @param e
* @param callback
*/
private static void handlerError(final Exception e, final ResultCallback callback) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onError(e, NETWORK_ERROR);
}
});
}
}
package com.hls.plugins.barcode.http;
import android.content.Intent;
import android.util.Log;
import com.hls.plugins.barcode.Util.NoSSLv3SocketFactory;
import com.hls.plugins.barcode.bean.ArgsBean;
import com.hls.plugins.barcode.bean.HttpInfoBean;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
/**
* Created by panx on 2017/3/8.
*/
public class HttpUtil {
/**
* 从网络获取json数据,(String byte[})
*
* @param httpInfoBean
* @return
*/
public static String get(HttpInfoBean httpInfoBean, ResultCallback<String> callback) {
try {
URL url = new URL(httpInfoBean.getUrl());
//打开连接
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setSSLSocketFactory(new NoSSLv3SocketFactory());
urlConnection.setRequestProperty("Authorization", httpInfoBean.getHeaders().getAuthorization());
urlConnection.setRequestProperty("Content-Type", httpInfoBean.getHeaders().getContentType());
if (200 == urlConnection.getResponseCode()) {
//得到输入流
InputStream is = urlConnection.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while (-1 != (len = is.read(buffer))) {
baos.write(buffer, 0, len);
baos.flush();
}
System.out.println(baos.toString());
baos.close();
urlConnection.disconnect();
callback.onResponse(baos.toString(), "");
return baos.toString("utf-8");
}
} catch (IOException e) {
e.printStackTrace();
callback.onError(e, null);
}
return null;
}
//获取其他页面的数据
/**
* POST请求获取数据
*/
public static String post(HttpInfoBean httpInfoBean, ResultCallback<String> callback) {
URL url = null;
try {
url = new URL(httpInfoBean.getUrl());
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(httpInfoBean.getConfig().getTimeout());
connection.setReadTimeout(30000);
connection.setDoOutput(true);// 是否输入参数
connection.setDoInput(true);
connection.setSSLSocketFactory(new NoSSLv3SocketFactory());
connection.setRequestProperty("Authorization", httpInfoBean.getHeaders().getAuthorization());
connection.setRequestProperty("Content-Type", httpInfoBean.getHeaders().getContentType());
connection.connect();
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(httpInfoBean.getData());
out.flush();
out.close();
//读取响应
BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String lines;
StringBuffer sb = new StringBuffer("");
while ((lines = reader.readLine()) != null) {
lines = new String(lines.getBytes(), "utf-8");
sb.append(lines);
}
callback.onResponse(sb.toString(), null);
reader.close();
// 断开连接
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
callback.onError(e, null);
}
return null;
}
}
package com.hls.plugins.barcode.http;
/**
* Created by panx on 2017/3/8.
*/
public abstract class ResultCallback<T> {
public abstract void onError(Exception e,String error);
public abstract void onResponse(T response,String result);
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<customFonts key="customFonts">
<array key="PingFang.ttc">
<string>PingFangSC-Regular</string>
</array>
</customFonts>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BarcodeScannerViewController">
<connections>
<outlet property="InfoButton" destination="dUa-yG-CYW" id="eQW-oh-9dg"/>
<outlet property="NavigtionViewHeightContraint" destination="plg-P3-Lb2" id="BBI-rL-lDD"/>
<outlet property="bottomContentView" destination="I7I-FP-lE3" id="jDc-bF-EU4"/>
<outlet property="bottomScanLabel" destination="dZo-gO-a5K" id="lDt-Eo-1Zr"/>
<outlet property="contentViewYContraint" destination="SNp-GX-pZ4" id="jQP-9T-lis"/>
<outlet property="firstSubLabel" destination="dqA-6d-nke" id="UJQ-AE-ioU"/>
<outlet property="navigatorView" destination="ORQ-3l-69F" id="vgP-4Y-yyN"/>
<outlet property="renderView" destination="fhi-4B-jH5" id="z9t-AU-tkM"/>
<outlet property="scanHeightConstraint" destination="g08-Gj-gD7" id="6AO-UT-6LS"/>
<outlet property="scanView" destination="coV-y0-6Qq" id="B44-nx-jve"/>
<outlet property="scanWidthConstraint" destination="45o-Eu-mjG" id="ziq-nX-6Z7"/>
<outlet property="scan_LineView" destination="hBh-KE-Usx" id="1ko-d2-Hvm"/>
<outlet property="secondSubLabel" destination="RkP-RS-WsT" id="J72-3O-q7k"/>
<outlet property="subtitle" destination="mcj-Ti-Ay4" id="2Ty-JU-b0C"/>
<outlet property="titleNameLabel" destination="dx1-8M-oah" id="94Q-c9-paE"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" horizontalHuggingPriority="320" verticalHuggingPriority="320" translatesAutoresizingMaskIntoConstraints="NO" id="fhi-4B-jH5">
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
<subviews>
<view alpha="0.80000000000000004" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QRS-qs-xQS">
<rect key="frame" x="0.0" y="0.0" width="375" height="60"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="锁定审核通过" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mcj-Ti-Ay4">
<rect key="frame" x="53" y="8" width="279" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="31T-eb-ogr"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="mcj-Ti-Ay4" firstAttribute="bottom" secondItem="QRS-qs-xQS" secondAttribute="bottomMargin" id="Yks-s0-DRw"/>
<constraint firstAttribute="trailing" secondItem="mcj-Ti-Ay4" secondAttribute="trailing" constant="43" id="ahk-Uz-Tne"/>
<constraint firstItem="mcj-Ti-Ay4" firstAttribute="leading" secondItem="QRS-qs-xQS" secondAttribute="leading" constant="53" id="oMN-sF-Wca"/>
<constraint firstAttribute="height" constant="60" id="p7C-Dq-fRV"/>
</constraints>
</view>
<view alpha="0.80000000000000004" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gQX-sq-tIi">
<rect key="frame" x="0.0" y="60" width="67.5" height="240"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<view alpha="0.80000000000000004" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Vpt-Pk-QDC">
<rect key="frame" x="307.5" y="60" width="67.5" height="240"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<view alpha="0.80000000000000004" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="I7I-FP-lE3">
<rect key="frame" x="0.0" y="300" width="375" height="303"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请扫描报销单上的二维码" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dZo-gO-a5K">
<rect key="frame" x="0.0" y="12" width="375" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="kua-Rb-BJ1"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="dZo-gO-a5K" firstAttribute="leading" secondItem="I7I-FP-lE3" secondAttribute="leading" id="NXY-f0-mw3"/>
<constraint firstAttribute="trailing" secondItem="dZo-gO-a5K" secondAttribute="trailing" id="ogO-i9-Y4o"/>
<constraint firstItem="dZo-gO-a5K" firstAttribute="top" secondItem="I7I-FP-lE3" secondAttribute="top" constant="12" id="xNf-cV-bhX"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="coV-y0-6Qq">
<rect key="frame" x="67.5" y="60" width="240" height="240"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fzL-eo-y5Z">
<rect key="frame" x="-2" y="-2" width="22" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="X57-Je-yL5"/>
<constraint firstAttribute="width" constant="22" id="aqW-jc-1dh"/>
</constraints>
<state key="normal" image="scan_1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9pK-k2-uXa">
<rect key="frame" x="-2" y="222" width="22" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="a3a-il-iQ9"/>
<constraint firstAttribute="width" constant="22" id="teK-fI-OFH"/>
</constraints>
<state key="normal" image="scan_3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9bp-TF-hEo">
<rect key="frame" x="220" y="222" width="22" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="OMz-Yb-91f"/>
<constraint firstAttribute="width" constant="22" id="tPY-h2-gao"/>
</constraints>
<state key="normal" image="scan_4"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="05c-9n-gsg">
<rect key="frame" x="220" y="-2" width="22" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="22" id="0zB-PJ-ybx"/>
<constraint firstAttribute="height" constant="22" id="rnF-TK-P30"/>
</constraints>
<state key="normal" image="scan_2"/>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="hly_line_scan.png" translatesAutoresizingMaskIntoConstraints="NO" id="hBh-KE-Usx">
<rect key="frame" x="0.0" y="0.0" width="240" height="6"/>
<constraints>
<constraint firstAttribute="height" constant="6" id="XmO-Ys-D4e"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="240" id="45o-Eu-mjG"/>
<constraint firstAttribute="trailing" secondItem="9bp-TF-hEo" secondAttribute="trailing" constant="-2" id="7Mh-Do-Bzm"/>
<constraint firstAttribute="trailing" secondItem="05c-9n-gsg" secondAttribute="trailing" constant="-2" id="G2s-8F-6tr"/>
<constraint firstAttribute="trailing" secondItem="hBh-KE-Usx" secondAttribute="trailing" id="LBr-UC-IBf"/>
<constraint firstItem="9pK-k2-uXa" firstAttribute="leading" secondItem="fzL-eo-y5Z" secondAttribute="leading" id="MJX-p3-1w5"/>
<constraint firstItem="hBh-KE-Usx" firstAttribute="top" secondItem="coV-y0-6Qq" secondAttribute="top" id="a7i-33-3hx"/>
<constraint firstAttribute="bottom" secondItem="9pK-k2-uXa" secondAttribute="bottom" constant="-4" id="cwc-qp-4ia"/>
<constraint firstItem="hBh-KE-Usx" firstAttribute="leading" secondItem="coV-y0-6Qq" secondAttribute="leading" id="fQu-hU-11S"/>
<constraint firstAttribute="height" constant="240" id="g08-Gj-gD7"/>
<constraint firstItem="fzL-eo-y5Z" firstAttribute="leading" secondItem="coV-y0-6Qq" secondAttribute="leading" constant="-2" id="its-BA-3Tl"/>
<constraint firstItem="05c-9n-gsg" firstAttribute="top" secondItem="coV-y0-6Qq" secondAttribute="top" constant="-2" id="nCs-LI-3YP"/>
<constraint firstItem="fzL-eo-y5Z" firstAttribute="top" secondItem="coV-y0-6Qq" secondAttribute="top" constant="-2" id="qMW-WA-RQ3"/>
<constraint firstAttribute="bottom" secondItem="9bp-TF-hEo" secondAttribute="bottom" constant="-4" id="zH5-iV-czq"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="..." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dqA-6d-nke">
<rect key="frame" x="4" y="554" width="367" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="..." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RkP-RS-WsT">
<rect key="frame" x="4" y="580" width="367" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="I7I-FP-lE3" secondAttribute="trailing" id="1wq-xI-nCA"/>
<constraint firstAttribute="trailing" secondItem="RkP-RS-WsT" secondAttribute="trailing" constant="4" id="AIZ-B0-4Al"/>
<constraint firstAttribute="trailing" secondItem="QRS-qs-xQS" secondAttribute="trailing" id="Icv-kj-kJx"/>
<constraint firstAttribute="trailing" secondItem="Vpt-Pk-QDC" secondAttribute="trailing" id="LPn-7L-Kq8"/>
<constraint firstItem="dqA-6d-nke" firstAttribute="leading" secondItem="fhi-4B-jH5" secondAttribute="leading" constant="4" id="QOo-aU-G1T"/>
<constraint firstAttribute="trailing" secondItem="dqA-6d-nke" secondAttribute="trailing" constant="4" id="WaE-7J-9EE"/>
<constraint firstItem="gQX-sq-tIi" firstAttribute="bottom" secondItem="coV-y0-6Qq" secondAttribute="bottom" id="a1h-r0-1Xi"/>
<constraint firstItem="coV-y0-6Qq" firstAttribute="leading" secondItem="gQX-sq-tIi" secondAttribute="trailing" id="aOT-xE-gH4"/>
<constraint firstItem="Vpt-Pk-QDC" firstAttribute="leading" secondItem="coV-y0-6Qq" secondAttribute="trailing" id="bLH-b9-gcJ"/>
<constraint firstItem="I7I-FP-lE3" firstAttribute="leading" secondItem="fhi-4B-jH5" secondAttribute="leading" id="dOS-Cd-6Lc"/>
<constraint firstItem="RkP-RS-WsT" firstAttribute="leading" secondItem="fhi-4B-jH5" secondAttribute="leading" constant="4" id="djB-Dh-QpH"/>
<constraint firstItem="gQX-sq-tIi" firstAttribute="top" secondItem="QRS-qs-xQS" secondAttribute="bottom" id="itr-Cz-n1g"/>
<constraint firstItem="Vpt-Pk-QDC" firstAttribute="bottom" secondItem="coV-y0-6Qq" secondAttribute="bottom" id="l0z-go-2R3"/>
<constraint firstAttribute="bottom" secondItem="RkP-RS-WsT" secondAttribute="bottom" constant="5" id="mSm-QO-zP4"/>
<constraint firstItem="QRS-qs-xQS" firstAttribute="leading" secondItem="fhi-4B-jH5" secondAttribute="leading" id="omc-ho-r0R"/>
<constraint firstItem="I7I-FP-lE3" firstAttribute="top" secondItem="coV-y0-6Qq" secondAttribute="bottom" id="ot3-ss-ska"/>
<constraint firstItem="RkP-RS-WsT" firstAttribute="top" secondItem="dqA-6d-nke" secondAttribute="bottom" constant="8" id="qlq-7H-dpG"/>
<constraint firstItem="gQX-sq-tIi" firstAttribute="leading" secondItem="fhi-4B-jH5" secondAttribute="leading" id="u3E-cK-odS"/>
<constraint firstItem="coV-y0-6Qq" firstAttribute="top" secondItem="QRS-qs-xQS" secondAttribute="bottom" multiplier="1:1" id="ukM-pB-OrC"/>
<constraint firstAttribute="bottom" secondItem="I7I-FP-lE3" secondAttribute="bottom" id="vp5-WQ-gF9"/>
<constraint firstItem="Vpt-Pk-QDC" firstAttribute="top" secondItem="QRS-qs-xQS" secondAttribute="bottom" id="wZc-mZ-1du"/>
</constraints>
</view>
<view contentMode="scaleToFill" horizontalHuggingPriority="320" verticalHuggingPriority="320" translatesAutoresizingMaskIntoConstraints="NO" id="ORQ-3l-69F">
<rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wgx-Bv-caG">
<rect key="frame" x="18" y="29" width="26" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="g5k-HL-5hX"/>
<constraint firstAttribute="width" constant="26" id="vhe-tR-vci"/>
</constraints>
<state key="normal" image="hly_backimg.png"/>
<state key="highlighted" image="hly_backimg.png"/>
<state key="focused" image="common_titlebar_btn_back_light_pressed"/>
<connections>
<action selector="dimissScan:" destination="-1" eventType="touchUpInside" id="VYP-bJ-FHn"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="扫描二维码" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dx1-8M-oah">
<rect key="frame" x="135.5" y="25.5" width="105" height="29.5"/>
<fontDescription key="fontDescription" name="PingFangSC-Regular" family="PingFang SC" pointSize="21"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dUa-yG-CYW">
<rect key="frame" x="333" y="27.5" width="26" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="26" id="jUV-2P-531"/>
<constraint firstAttribute="height" constant="26" id="zYF-1u-Ngz"/>
</constraints>
<state key="normal" image="hly_alertimg.png"/>
</button>
</subviews>
<color key="backgroundColor" red="0.0039215686274509803" green="0.027450980392156862" blue="0.074509803921568626" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="dUa-yG-CYW" secondAttribute="trailing" constant="16" id="7ZE-hk-nkz"/>
<constraint firstItem="dUa-yG-CYW" firstAttribute="centerY" secondItem="Wgx-Bv-caG" secondAttribute="centerY" id="EmL-Dl-4gm"/>
<constraint firstItem="dx1-8M-oah" firstAttribute="centerY" secondItem="Wgx-Bv-caG" secondAttribute="centerY" id="Q8t-v1-0Jh"/>
<constraint firstItem="dx1-8M-oah" firstAttribute="centerX" secondItem="ORQ-3l-69F" secondAttribute="centerX" id="UgZ-E8-TL2"/>
<constraint firstAttribute="bottom" secondItem="Wgx-Bv-caG" secondAttribute="bottom" constant="13" id="eMx-QC-DOk"/>
<constraint firstAttribute="height" constant="64" id="plg-P3-Lb2"/>
<constraint firstItem="Wgx-Bv-caG" firstAttribute="leading" secondItem="ORQ-3l-69F" secondAttribute="leadingMargin" constant="10" id="zbb-pg-XCQ"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="coV-y0-6Qq" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="2kd-vg-etQ"/>
<constraint firstItem="fhi-4B-jH5" firstAttribute="trailing" secondItem="ORQ-3l-69F" secondAttribute="trailing" id="5Tj-72-XJk"/>
<constraint firstItem="fhi-4B-jH5" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="6Cu-eR-D4z"/>
<constraint firstAttribute="bottom" secondItem="fhi-4B-jH5" secondAttribute="bottom" id="Cp5-zM-3Y6"/>
<constraint firstItem="ORQ-3l-69F" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="PGi-n5-KcT"/>
<constraint firstItem="fhi-4B-jH5" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="64" id="SNp-GX-pZ4"/>
<constraint firstAttribute="trailing" secondItem="fhi-4B-jH5" secondAttribute="trailing" id="bmv-Xo-oaY"/>
<constraint firstItem="QRS-qs-xQS" firstAttribute="top" secondItem="ORQ-3l-69F" secondAttribute="bottom" id="eiT-5S-Xdq"/>
<constraint firstItem="fhi-4B-jH5" firstAttribute="leading" secondItem="ORQ-3l-69F" secondAttribute="leading" id="xbR-7O-i4b"/>
</constraints>
<point key="canvasLocation" x="291.5" y="345.5"/>
</view>
</objects>
<resources>
<image name="common_titlebar_btn_back_light_pressed" width="24" height="36"/>
<image name="hly_alertimg.png" width="38" height="38"/>
<image name="hly_backimg.png" width="38" height="40"/>
<image name="hly_line_scan.png" width="320" height="12"/>
<image name="scan_1" width="19" height="19"/>
<image name="scan_2" width="19" height="19"/>
<image name="scan_3" width="19" height="19"/>
<image name="scan_4" width="19" height="19"/>
</resources>
</document>
//
// BarcodeScannerViewController.h
// barcode
//
// Created by jingren on 16/9/11.
// Copyright © 2016年 jieweifu. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol BarcodeScannerDelegate <NSObject>
@optional
#pragma mark - Listening for Reader Status
- (void)reader:(NSDictionary *)result;
/**
* @abstract Tells the delegate that the user wants to stop scanning QRCodes.
* @param reader The reader view controller that the user wants to stop.
* @since 1.0.0
*/
- (void)readerDidCancel;
@end
@interface BarcodeScannerViewController : UIViewController
@property (nonatomic, weak) id<BarcodeScannerDelegate> delegate;
@property (weak, nonatomic) IBOutlet UILabel *firstSubLabel;
@property (weak, nonatomic) IBOutlet UILabel *secondSubLabel;
@property (nonatomic,strong) NSDictionary *requestDic;
@property (nonatomic,strong) NSString *firstString;
@property (nonatomic,strong) NSString *secondString;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *scanWidthConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *scanHeightConstraint;
@property (nonatomic,strong) NSDictionary *messageDic;//显示信息
@property (nonatomic,strong) NSString *operationType;//处理类型
@property (nonatomic,strong) NSArray *requestList;//http请求列表
@end
//
// BarcodeScannerViewController.m
// barcode
//
// Created by jingren on 16/9/11.
// Copyright © 2016年 jieweifu. All rights reserved.
//
#import "UIView+Toast.h"
#import "BarcodeScannerViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "CustomScanView.h"
#import "Reachability.h"
#import "HLYCustomButton.h"
#define kwidth [UIScreen mainScreen].bounds.size.width
#define kheight [UIScreen mainScreen].bounds.size.height
#define isIphoneX [UIScreen mainScreen].bounds.size.height == 812.0f
@interface BarcodeScannerViewController ()<AVCaptureMetadataOutputObjectsDelegate, BarcodeScannerDelegate>
@property (weak, nonatomic) IBOutlet UIView *renderView;
@property (weak, nonatomic) IBOutlet UIView *scanView;
@property (weak, nonatomic) IBOutlet UILabel *subtitle;//扫描框上
@property (strong, nonatomic) AVAudioPlayer *beepPlayer;
@property BOOL isFlashLightOn;
@property (nonatomic, strong) AVCaptureSession *session;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewYContraint;
@property (weak, nonatomic) IBOutlet UILabel *titleNameLabel;//
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *NavigtionViewHeightContraint;
@property (strong, nonatomic) NSTimer *timerScan;
@property (weak, nonatomic) IBOutlet UIView *navigatorView;
@property BOOL isDismissViewController;
@property (weak, nonatomic) IBOutlet UILabel *bottomScanLabel;
@property (weak, nonatomic) IBOutlet UIView *bottomContentView;
@property (weak, nonatomic) IBOutlet UIButton *InfoButton;
@property (weak, nonatomic) IBOutlet UIImageView *scan_LineView;
@property (nonatomic,strong) CustomScanView *customScanView;
@property (nonatomic,strong) NetWorkView *networkView;
@property (nonatomic,strong) NSURLSessionDataTask *dataTask;
@property (nonatomic,strong) UIView *loadingView;
@property (nonatomic,strong) CSToastStyle *toastStyle;
@property (nonatomic, assign) CGFloat delayTime;
@end
@implementation BarcodeScannerViewController{
BOOL isLightEnable;
}
- (IBAction)dimissScan:(id)sender {
[self stopScanning];
if([self.delegate respondsToSelector:@selector(reader:)]){
[self.delegate reader:@{@"type":@"CLOSE"}];
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
}
- (void) setFlashOn: (BOOL)on{
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
[device lockForConfiguration:nil];
if (on) {
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
} else {
[device setTorchMode:AVCaptureTorchModeOff];
[device setFlashMode:AVCaptureFlashModeOff];
}
[device unlockForConfiguration];
}
}
}
- (void)updateViewConstraints {
[super updateViewConstraints];
self.NavigtionViewHeightContraint.constant = isIphoneX ? 88:64;
self.contentViewYContraint.constant = isIphoneX ? 88:64;
}
#pragma mark lazyload
- (CustomScanView *)customScanView{
if(_customScanView == nil){
_customScanView = [[CustomScanView alloc] initWithFrame:CGRectMake(0, isIphoneX ? 88:64, kwidth, kheight-(isIphoneX ? 88:64))];
_customScanView.hidden = YES;
}
return _customScanView;
}
- (NetWorkView *)networkView{
if(_networkView == nil){
_networkView = [[NetWorkView alloc] initWithFrame:CGRectMake(0, isIphoneX ? 88:64, kwidth, kheight-(isIphoneX ? 88:64))];
_networkView.hidden = YES;
}
return _networkView;
}
- (CSToastStyle *)toastStyle{
if(_toastStyle == nil){
_toastStyle = [[CSToastStyle alloc] initWithDefaultStyle];
_toastStyle.titleAlignment = NSTextAlignmentCenter;
_toastStyle.titleNumberOfLines = 0;
_toastStyle.titleFont = [UIFont systemFontOfSize:15];
_toastStyle.messageFont = [UIFont systemFontOfSize:13];
}
return _toastStyle;
}
- (UIView *)loadingView{
if(_loadingView == nil){
_loadingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 180, 40)];
UILabel *loadLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 120, 30)];
loadLabel.font = [UIFont systemFontOfSize:15];
loadLabel.textColor = [UIColor whiteColor];
loadLabel.textAlignment = NSTextAlignmentCenter;
loadLabel.text = self.messageDic[@"tipLoading"];
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(loadLabel.frame)+10, 5, 1, 30)];
line.backgroundColor = [UIColor colorWithRed:80/255.0 green:80/255.0 blue:80/255.0 alpha:1];
[_loadingView addSubview:line];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(CGRectGetMaxX(line.frame)+5, 5, 30, 30);
[btn setTitle:@"X" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(closeToast) forControlEvents:UIControlEventTouchUpInside];
[_loadingView addSubview:loadLabel];
[_loadingView addSubview:btn];
_loadingView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:0.9];
_loadingView.layer.cornerRadius = 20;
_loadingView.layer.masksToBounds = YES;
}
return _loadingView;
}
#pragma mark liftcycle
- (void)viewDidLoad {
[super viewDidLoad];
if(kwidth == 320){
self.scanWidthConstraint.constant = 200;
self.scanHeightConstraint.constant = 200;
}
self.NavigtionViewHeightContraint.constant = isIphoneX ? 88:64;
[self initResource];
[self initCapture];
[self initSubViews];
self.title = self.messageDic[@"barTitle"];
self.titleNameLabel.text = self.messageDic[@"barTitle"];
if([self.messageDic[@"explainFlag"] boolValue] == true){
self.InfoButton.hidden = NO;
[self.InfoButton addTarget:self action:@selector(infoAction) forControlEvents:UIControlEventTouchUpInside];
}else{
self.InfoButton.hidden = YES;
}
self.subtitle.text = self.messageDic[@"title"];
self.bottomScanLabel.text = self.messageDic[@"tipScan"];
self.firstSubLabel.text = self.messageDic[@"footerFirst"];
self.secondSubLabel.text = self.messageDic[@"footerSecond"];
}
- (void)initResource{
self.isFlashLightOn = YES;
[self setNeedsStatusBarAppearanceUpdate];
NSString * wavPath = [[NSBundle mainBundle] pathForResource:@"beep" ofType:@"wav"];
NSData* data = [[NSData alloc] initWithContentsOfFile:wavPath];
self.beepPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
if(self.messageDic[@"delayTime"]){
_delayTime = [self.messageDic[@"delayTime"] floatValue];
}
}
- (void)initSubViews{
[self startScanning];
[CSToastManager setTapToDismissEnabled:NO];
[CSToastManager setQueueEnabled:NO];
[self addHandleButton];
[self.view addSubview:self.networkView];
[self.view addSubview:self.customScanView];
self.customScanView.msgLabel.text = self.messageDic[@"tipOffline"];
[_customScanView.openBtn addTarget:self action:@selector(openAction) forControlEvents:UIControlEventTouchUpInside];
[_customScanView.openBtn setTitle:self.messageDic[@"openButton"] forState:UIControlStateNormal];
_customScanView.firstLabel.text = self.messageDic[@"footerFirst"];
_customScanView.secondLabel.text = self.messageDic[@"footerSecond"];
NetworkStatus status = [self getNetWorkStatus];
if(status == NotReachable){//没有网络
[self.view makeToast:self.messageDic[@"tipNetworkError"] duration:1.0 position:CSToastPositionCenter style:_toastStyle];
_scanView.hidden = YES;
_customScanView.hidden = YES;
_networkView.hidden = NO;
_networkView.msgLabel.text = self.messageDic[@"tipNetworkError"];
}else if ([_operationType isEqualToString:@"REVIEW"]){
[self handle_REVIEW:nil];
}
}
- (void)addHandleButton{
CGRect handRect = CGRectZero;
CGRect lightRect = CGRectZero;
CGFloat btnWidth = 90;
CGFloat swidth = kwidth;
if([self.messageDic[@"inputFlag"] boolValue] == false && [self.messageDic[@"lightFlag"] boolValue] == false){
}else if([self.messageDic[@"lightFlag"] boolValue] == false){
handRect = CGRectMake((swidth-btnWidth)/2, 65, btnWidth, 80);
}else if([self.messageDic[@"inputFlag"] boolValue] == false){
lightRect = CGRectMake((swidth-btnWidth)/2, 65, btnWidth, 80);
}else{
handRect = CGRectMake(swidth/2-110, 65, btnWidth, 80);
lightRect = CGRectMake(swidth/2+20, 65, btnWidth, 80);
}
HLYCustomButton *handBtn = [[HLYCustomButton alloc] initWithFrame:handRect imgName:@"hly_handwork" titleString:self.messageDic[@"tipInput"]];
[handBtn addTarget:self action:@selector(tapAction) forControlEvents:UIControlEventTouchUpInside];
[_bottomContentView addSubview:handBtn];
HLYCustomButton *ligthenBtn = [[HLYCustomButton alloc] initWithFrame:lightRect imgName:@"light_close" titleString:self.messageDic[@"tipLightOn"]];
[ligthenBtn addTarget:self action:@selector(lightAction:) forControlEvents:UIControlEventTouchUpInside];
[_bottomContentView addSubview:ligthenBtn];
}
//获取当前的网络状态 0:无网 1:WIFI 2:蜂窝网络
- (NetworkStatus)getNetWorkStatus{
Reachability *reachability = [Reachability reachabilityWithHostName:@"www.apple.com"];
return [reachability currentReachabilityStatus];
}
#pragma mark operation type
//财务审核通过扫码
- (void)handle_AUDIT_PASS:(NSString *)code{
NSDictionary *dic = [_requestList firstObject];
[self.view showToast:self.loadingView duration:MAXFLOAT position:[NSValue valueWithCGPoint:CGPointMake(kwidth/2, kheight/2)] completion:nil];
NSMutableDictionary *body = [dic[@"data"] mutableCopy];
[body setObject:code forKey:@"code"];
__weak BarcodeScannerViewController *weakSelf = self;
_dataTask = [NetWorkTool request:dic[@"url"] header:dic[@"headers"] method:dic[@"method"] params:body success:^(id response) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
});
if(response && ![response isEqual:[NSNull null]]){
if([[NSString stringWithFormat:@"%@",response[@"code"]] isEqualToString:@"0000"]){
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view makeToast:response[@"msg"] duration:1.0f position:CSToastPositionCenter title:[NSString stringWithFormat:@"%@\n%@",response[@"expenseReport"][@"applicantName"],response[@"expenseReport"][@"businessCode"]] image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view makeToast:response[@"msg"] duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}
} failure:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}];
}
//财务审核收到扫码
- (void)handle_RECEIVE:(NSString *)code{
NSDictionary *dic = [_requestList firstObject];
[self.view showToast:self.loadingView duration:MAXFLOAT position:[NSValue valueWithCGPoint:CGPointMake(kwidth/2, kheight/2)] completion:nil];
NSMutableDictionary *body = [dic[@"data"] mutableCopy];
[body setObject:code forKey:@"code"];
__weak BarcodeScannerViewController *weakSelf = self;
_dataTask = [NetWorkTool request:dic[@"url"] header:dic[@"headers"] method:dic[@"method"] params:body success:^(id response) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
});
if(response && ![response isEqual:[NSNull null]]){
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view makeToast:response[@"msg"] duration:1.0 position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}
} failure:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}];
}
//财务审核驳回扫码
- (void)handle_AUDIT:(NSString *)code{
NSDictionary *dic = [_requestList firstObject];
[self.view showToast:self.loadingView duration:MAXFLOAT position:[NSValue valueWithCGPoint:CGPointMake(kwidth/2, kheight/2)] completion:nil];
NSMutableDictionary *body = [dic[@"data"] mutableCopy];
[body setObject:code forKey:@"code"];
__weak BarcodeScannerViewController *weakSelf = self;
_dataTask = [NetWorkTool request:dic[@"url"] header:dic[@"headers"] method:dic[@"method"] params:body success:^(id response) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
if(response && ![response isEqual:[NSNull null]]){
if([[NSString stringWithFormat:@"%@",response[@"code"]] isEqualToString:@"0000"]){
[weakSelf.view makeToast:response[@"msg"] duration:1.0 position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
if([weakSelf.delegate respondsToSelector:@selector(reader:)]){
[weakSelf.delegate reader:@{@"type":weakSelf.operationType,@"message":@{@"code":code,@"response":response}}];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf dismissViewControllerAnimated:YES completion:nil];
});
}
}];
}else{
[weakSelf.view makeToast:response[@"msg"] duration:1.0f position:CSToastPositionCenter style:weakSelf.toastStyle];
[weakSelf startScanning];
}
}else{
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
}
});
} failure:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}];
}
//财务退单扫码
- (void)handle_BACK:(NSString *)code{
NSDictionary *dic = [_requestList firstObject];
[self.view showToast:self.loadingView duration:MAXFLOAT position:[NSValue valueWithCGPoint:CGPointMake(kwidth/2, kheight/2)] completion:nil];
NSMutableDictionary *body = [dic[@"data"] mutableCopy];
[body setObject:code forKey:@"code"];
__weak BarcodeScannerViewController *weakSelf = self;
_dataTask = [NetWorkTool request:dic[@"url"] header:dic[@"headers"] method:dic[@"method"] params:body success:^(id response) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
if(response && ![response isEqual:[NSNull null]]){
if([[NSString stringWithFormat:@"%@",response[@"code"]] isEqualToString:@"0000"]){
[weakSelf.view makeToast:response[@"msg"] duration:1.0 position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
if([weakSelf.delegate respondsToSelector:@selector(reader:)]){
[weakSelf.delegate reader:@{@"type":weakSelf.operationType,@"message":@{@"code":code,@"response":response}}];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf dismissViewControllerAnimated:YES completion:nil];
});
}
}];
}else{
[weakSelf.view makeToast:response[@"msg"] duration:1.0f position:CSToastPositionCenter style:weakSelf.toastStyle];
[weakSelf startScanning];
}
}else{
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
}
});
} failure:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}];
}
//检查是否web在线
- (void)handle_REVIEW:(NSString *)code{
__weak BarcodeScannerViewController *weakSelf = self;
NSDictionary *webDic = self.requestList[1];
[self.view showToast:self.loadingView duration:MAXFLOAT position:[NSValue valueWithCGPoint:CGPointMake(kwidth/2, kheight/2)] completion:nil];
_dataTask = [NetWorkTool request:webDic[@"url"] header:webDic[@"headers"] method:webDic[@"method"] params:webDic[@"data"] success:^(id response) {
if(response && ![response isEqual:[NSNull null]]){
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.customScanView.openBtn.alpha = 1.0;
[weakSelf.view hideToasts];
if([[NSString stringWithFormat:@"%@",response[@"online"]] isEqualToString:@"1"]){
weakSelf.scanView.hidden = NO;
weakSelf.networkView.hidden = YES;
weakSelf.customScanView.hidden = YES;
if(code){
[weakSelf handle_REVIEW_Open:code];
}else{
[weakSelf startScanning];
}
}else{
weakSelf.scanView.hidden = YES;
weakSelf.networkView.hidden = YES;
weakSelf.customScanView.hidden = NO;
weakSelf.customScanView.msgLabel.text = self.messageDic[@"tipOffline"];
}
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}
} failure:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}];
}
//财务读图审核扫码
- (void)handle_REVIEW_Open:(NSString *)code{
__weak BarcodeScannerViewController *weakSelf = self;
NSDictionary *webDic = [self.requestList firstObject];
NSMutableDictionary *body = [webDic[@"data"] mutableCopy];
[body setObject:code forKey:@"code"];
[self.view showToast:self.loadingView duration:MAXFLOAT position:[NSValue valueWithCGPoint:CGPointMake(kwidth/2, kheight/2)] completion:nil];
_dataTask = [NetWorkTool request:webDic[@"url"] header:webDic[@"headers"] method:webDic[@"method"] params:body success:^(id response) {
if(response && ![response isEqual:[NSNull null]]){
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
if([[NSString stringWithFormat:@"%@",response[@"code"]] isEqualToString:@"0000"]){
[weakSelf.view makeToast:response[@"msg"] duration:1.0 position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
if([weakSelf.delegate respondsToSelector:@selector(reader:)]){
[weakSelf.delegate reader:@{@"type":weakSelf.operationType}];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf dismissViewControllerAnimated:YES completion:nil];
});
}
}];
}else{
[weakSelf.view makeToast:response[@"msg"] duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
}
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}
} failure:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}];
}
//发票验证扫码
- (void)handle_INVOICE:(NSString *)code{
__weak BarcodeScannerViewController *weakSelf = self;
NSDictionary *webDic = [self.requestList firstObject];
NSMutableDictionary *body = [webDic[@"data"] mutableCopy];
[body setObject:code forKey:@"code"];
[self.view showToast:self.loadingView duration:MAXFLOAT position:[NSValue valueWithCGPoint:CGPointMake(kwidth/2, kheight/2)] completion:nil];
_dataTask = [NetWorkTool request:webDic[@"url"] header:webDic[@"headers"] method:webDic[@"method"] params:body success:^(id response) {
if(response && ![response isEqual:[NSNull null]]){
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
if([[NSString stringWithFormat:@"%@",response[@"code"]] isEqualToString:@"0000"]){
[weakSelf.view makeToast:response[@"msg"] duration:1.0 position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
if([weakSelf.delegate respondsToSelector:@selector(reader:)]){
[weakSelf.delegate reader:@{@"type":weakSelf.operationType,@"message":@{@"code":code,@"response":response}}];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf dismissViewControllerAnimated:YES completion:nil];
});
}
}];
}else{
[weakSelf.view makeToast:response[@"msg"] duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
}
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}
} failure:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.view hideToasts];
[weakSelf.view makeToast:@"请求发生错误,请稍后再试" duration:1.0f position:CSToastPositionCenter title:nil image:nil style:weakSelf.toastStyle completion:^(BOOL didTap) {
[weakSelf startScanning];
}];
});
}];
}
#pragma mark action
//MARK: 开启灯光
- (void)lightAction:(HLYCustomButton *)btn{
isLightEnable = !isLightEnable;
if(isLightEnable){
[btn setClickTitle:self.messageDic[@"tipLightOff"] isOpen:isLightEnable];
}else{
[btn setClickTitle:self.messageDic[@"tipLightOn"] isOpen:isLightEnable];
}
[self setFlashOn:isLightEnable];
}
//MARK: 提示信息
- (void)infoAction{
if([self.delegate respondsToSelector:@selector(reader:)]){
[self.delegate reader:@{@"type":@"EXPLAIN"}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
}
}
- (void)openAction{
_customScanView.openBtn.alpha = .9;
[self handle_REVIEW:nil];
}
//MARK: 手动输入
- (void)tapAction{
if([self.delegate respondsToSelector:@selector(reader:)]){
[self.delegate reader:@{@"type":@"INPUT"}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
}
}
//MARK: 停止处理..
- (void)closeToast{
[_dataTask cancel];
[self.view hideToasts];
[self startScanning];
}
//MARK: 开始扫描
- (void)startScanning
{
if (![self.session isRunning]) {
[self.session startRunning];
}
if(self.timerScan)
{
[self.timerScan invalidate];
self.timerScan = nil;
}
[self scanAnimate];
}
- (void) scanAnimate{
[self.scan_LineView.layer addAnimation:[self animation] forKey:nil];
}
- (CABasicAnimation *)animation{
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
animation.duration = 3;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.repeatCount = MAXFLOAT;
animation.fromValue = @(0);
animation.toValue = @(self.scanHeightConstraint.constant);
return animation;
}
//MARK: 停止扫描
- (void)stopScanning;
{
if ([self.session isRunning]) {
[self.session stopRunning];
}
[self.scan_LineView.layer removeAllAnimations];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//MARK: 初始化设备
- (void)initCapture
{
//获取摄像设备
AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//创建输入流
AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
if (!input) return;
//创建输出流
AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
//设置代理 在主线程里刷新
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//初始化链接对象
self.session = [[AVCaptureSession alloc]init];
//高质量采集率
[self.session setSessionPreset:AVCaptureSessionPresetHigh];
[self.session addInput:input];
[self.session addOutput:output];
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
[output setRectOfInterest:CGRectMake((64)/kheight,((kwidth-240)/2)/kwidth,240/kheight,240/kwidth)];
AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
layer.videoGravity=AVLayerVideoGravityResizeAspectFill;
// layer.frame=self.view.layer.bounds;
// NSLog(@"%@", NSStringFromCGRect(self.renderView.frame));
layer.frame=CGRectMake(0, isIphoneX ? 88:64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
[self.view.layer insertSublayer:layer atIndex:0];
}
#pragma mark - AVCaptureMetadataOutputObjects Delegate Methods
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
NSString *result = @"";
for(AVMetadataObject *current in metadataObjects) {
if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]])
{
result = [(AVMetadataMachineReadableCodeObject *) current stringValue];
[self.beepPlayer play];
break;
}
}
[self stopScanning];
if([self getNetWorkStatus] == 0){
self.scanView.hidden = YES;
self.customScanView.hidden = YES;
self.networkView.hidden = NO;
return;
}
if(result){
if([[_operationType uppercaseString] isEqualToString:@"AUDIT_PASS"]){
[self handle_AUDIT_PASS:result];
}else if ([[_operationType uppercaseString] isEqualToString:@"RECEIVE"]){
[self handle_RECEIVE:result];
}else if ([[_operationType uppercaseString] isEqualToString:@"AUDIT"]){
[self handle_AUDIT:result];
}else if ([[_operationType uppercaseString] isEqualToString:@"BACK"]){
[self handle_BACK:result];
}
else if ([[_operationType uppercaseString] isEqualToString:@"REVIEW"]){
[self handle_REVIEW:result];
}else if ([[_operationType uppercaseString] isEqualToString:@"INVOICE"]){
[self handle_INVOICE:result];
}else if ([[_operationType uppercaseString]isEqualToString:@"SCAN"]){
if([self.delegate respondsToSelector:@selector(reader:)]){
[self.delegate reader:@{@"type":@"SCAN",@"code":result}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
}
}
}
}
#pragma mark-> 获取扫描区域的比例关系
-(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)readerViewBounds
{
CGFloat x,y,width,height;
x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds);
y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds);
width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds);
height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds);
return CGRectMake(x, y, width, height);
}
#pragma mark 屏幕方向处理
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
@end
//
// CDVBarcodeScanner.h
// HelloCordova
//
// Created by jingren on 16/9/11.
//
//
#import <Cordova/CDV.h>
#import "BarcodeScannerViewController.h"
@interface CDVBarcodeScanner : CDVPlugin<BarcodeScannerDelegate>
@property (nonatomic, strong) NSString *currentCallbackId;
- (void)startScan:(CDVInvokedUrlCommand *)command;
- (void)hasPermission:(CDVInvokedUrlCommand *)command;
@end
//
// CDVBarcodeScanner.m
// HelloCordova
//
// Created by jingren on 16/9/11.
//
//
#import "CDVBarcodeScanner.h"
#import <AVFoundation/AVFoundation.h>
#import "BarcodeScannerViewController.h"
@implementation CDVBarcodeScanner
- (void)startScan:(CDVInvokedUrlCommand *)command{
self.currentCallbackId = command.callbackId;
NSLog(@"args: %@", [command argumentAtIndex:0]);
NSDictionary *dic = command.arguments.count == 0 ? [NSNull null] : [command argumentAtIndex:0];
[self.commandDelegate runInBackground:^{
BarcodeScannerViewController *barcodeCtrl = [[BarcodeScannerViewController alloc] initWithNibName:@"BarcodeScannerViewController" bundle:nil];
barcodeCtrl.delegate = self;
barcodeCtrl.messageDic = dic[@"message"];
// @{@"barTitle":@"在头部栏显示的标题,可空",
// @"explainFlag":@(YES),
// @"title":@"扫码框上方的标题,可空",
// @"tipScan":@"扫码框下方的提示,可空",
// @"inputFlag":@(YES),
// @"lightFlag":@(YES),
// @"tipInput":@"输入单号提示,可空",
// @"tipLightOn":@"打开",
// @"tipLightOff":@"关闭",
// @"tipLoading":@"调接口的过程中的提示",
// @"tipNetworkError":@"网络错误时的提示",
// @"tipOffline":@"没有打开web时的提示",
// @"openButton":@"我已打开按钮文字",
// @"footerFirst":@"底部提示第一行,可空",
// @"footerSecond": @"底部提示第二行,可空",
// @"delayTime":@"2"
// };
//REVIEW: 读图审核 AUDIT_PASS: 通过 AUDIT: 驳回 RECEIVE: 收到 SCAN:扫码 INVOICE:发票验证
barcodeCtrl.operationType = dic[@"operationType"];
barcodeCtrl.requestList = dic[@"requests"];
// @[@{@"url":@"https://apiuat.huilianyi.com/api/audit/scancode",@"method":@"POST",@"headers":@{@"Authorization":@"Bearer b46e27f1-5277-485b-817a-3ed2f26e4175",@"Content-Type":@"application/json"},@"data":@{@"operate":barcodeCtrl.operationType}},@{@"url":@"https://apiuat.huilianyi.com/api/audit/scancode/online/check",@"method":@"GET",@"headers":@{@"Authorization":@"Bearer b46e27f1-5277-485b-817a-3ed2f26e4175",@"Content-Type":@"application/json"}}];
barcodeCtrl.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
dispatch_async(dispatch_get_main_queue(), ^{
[self.viewController presentViewController:barcodeCtrl animated:YES completion:nil];
});
}];
}
- (void)reader:(NSDictionary *)result{
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result] callbackId:self.currentCallbackId];
}
- (void)readerDidCancel{
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR] callbackId:self.currentCallbackId];
}
-(void)hasPermission:(CDVInvokedUrlCommand *)command {
Boolean result = false;
//判断是否已授权
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (authStatus == AVAuthorizationStatusDenied||authStatus == AVAuthorizationStatusRestricted) {
result = false;
}
}
// 判断是否可以打开相机
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
result = true;
} else {
result = false;
}
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (status) {
// case AVAuthorizationStatusNotDetermined:{
// 许可对话没有出现,发起授权许可
//
// [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
//
// if (granted) {
// //第一次用户接受
// return true;
// }else{
// //用户拒绝
// return false;
// }
// }];
//
// [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
// if (!granted) { //用户拒绝
//
// }
// }];
// break;
// }
// case AVAuthorizationStatusAuthorized:{
// // 已经开启授权,可继续
// result = true;
// break;
// }
case AVAuthorizationStatusDenied:
case AVAuthorizationStatusRestricted:
// 用户明确地拒绝授权,或者相机设备无法访问
result = false;
break;
default:
break;
}
CDVPluginResult *pluginResult;
if(!result){
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"false"];
}else{
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"true"];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@end
//
// CustomScanView.h
// HandTest
//
// Created by Mr.xiao on 17/3/15.
//
//
#import <UIKit/UIKit.h>
@interface CustomScanView : UIView
@property (nonatomic,strong) UIImageView *imgView;
@property (nonatomic,strong) UILabel *msgLabel;
@property (nonatomic,strong) UIButton *openBtn;
@property (nonatomic,strong) UILabel *firstLabel;
@property (nonatomic,strong) UILabel *secondLabel;
@end
@interface NetWorkView : UIView
@property (nonatomic,strong) UIImageView *imgView;
@property (nonatomic,strong) UILabel *msgLabel;
@end
@interface NetWorkTool : NSObject
+ (instancetype)shareInstance;
+ (NSURLSessionDataTask *)request:(NSString *)url header:(NSDictionary *)header method:(NSString *)method params:(NSDictionary *)params success:(void (^)(id response))successBlock failure:(void(^)(NSError *error))failure;
@end
//
// CustomScanView.m
// HandTest
//
// Created by Mr.xiao on 17/3/15.
//
//
#import "CustomScanView.h"
@implementation CustomScanView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
[self initSubViews];
}
return self;
}
- (void)initSubViews{
CGSize size = self.frame.size;
self.backgroundColor = [UIColor colorWithRed:127.0/255.0 green:127.0/255.0 blue:127.0/255.0 alpha:1];
_imgView = [[UIImageView alloc] initWithFrame:CGRectMake((size.width-200)/2, 30, 200, 200)];
_imgView.image = [UIImage imageNamed:@"hly_pc"];
[self addSubview:_imgView];
_msgLabel = [[UILabel alloc] initWithFrame:CGRectMake((size.width-200)/2, CGRectGetMaxY(_imgView.frame)+20, 200, 50)];
_msgLabel.numberOfLines = 0;
_msgLabel.text = @"请按照页面下方提示\n先打开汇联易网站";
_msgLabel.textColor = [UIColor whiteColor];
_msgLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_msgLabel];
_openBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_openBtn.frame = CGRectMake((size.width-140)/2, CGRectGetMaxY(_msgLabel.frame)+20, 140, 35);
[_openBtn setTitle:@"我已打开" forState:UIControlStateNormal];
_openBtn.layer.cornerRadius = 15;
[_openBtn setBackgroundColor:[UIColor colorWithRed:23/255.0 green:147/255.0 blue:215/255.0 alpha:1]];
[self addSubview:_openBtn];
_secondLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, size.height-25-30, size.width-40, 30)];
_secondLabel.textColor = [UIColor whiteColor];
_secondLabel.font = [UIFont systemFontOfSize:15];
_secondLabel.numberOfLines = 0;
_secondLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_secondLabel];
_firstLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, CGRectGetMinY(_secondLabel.frame)-55, size.width-40, 50)];
_firstLabel.numberOfLines = 0;
_firstLabel.textColor = [UIColor whiteColor];
_firstLabel.font = [UIFont systemFontOfSize:15];
_firstLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_firstLabel];
}
@end
@implementation NetWorkView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
[self initSubViews];
}
return self;
}
- (void)initSubViews{
CGSize size = self.frame.size;
self.backgroundColor = [UIColor colorWithRed:127.0/255.0 green:127.0/255.0 blue:127.0/255.0 alpha:1];
_imgView = [[UIImageView alloc] initWithFrame:CGRectMake((size.width-200)/2, 50, 200, 200)];
_imgView.image = [UIImage imageNamed:@"hly_net"];
[self addSubview:_imgView];
_msgLabel = [[UILabel alloc] initWithFrame:CGRectMake((size.width-200)/2, 275, 200, 50)];
_msgLabel.numberOfLines = 0;
_msgLabel.text = @"当前网络不可用,请检查网络!";
_msgLabel.textColor = [UIColor whiteColor];
_msgLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_msgLabel];
}
@end
@implementation NetWorkTool
+ (instancetype)shareInstance{
static NetWorkTool *network;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
network = [[NetWorkTool alloc] init];
});
return network;
}
+ (NSURLSessionDataTask *)request:(NSString *)url header:(NSDictionary *)header method:(NSString *)method params:(NSDictionary *)params success:(void (^)(id response))successBlock failure:(void(^)(NSError *error))failure{
NSURL *Url = [NSURL URLWithString:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:Url];
[request setHTTPMethod:[method uppercaseString]];
if(params){ //设置请求体
[request setHTTPBody:[NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil]];
}//设置请求头
if(header){
[request setAllHTTPHeaderFields:header];
}
NSURLSessionDataTask *task = [[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(!error){
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
successBlock(result);
}else{
failure(error);
}
}];
[task resume];
return task;
}
@end
//
// CustomButton.h
// IonicTest
//
// Created by Mr.xiao on 2017/8/7.
//
//
#import <UIKit/UIKit.h>
@interface HLYCustomButton : UIButton
- (instancetype)initWithFrame:(CGRect)frame imgName:(NSString *)imgName titleString:(NSString *)title;
- (void)setClickTitle:(NSString *)title isOpen:(BOOL)isOpen;
@end
//
// CustomButton.m
// IonicTest
//
// Created by Mr.xiao on 2017/8/7.
//
//
#import "HLYCustomButton.h"
#define kImgWidth 60
@interface HLYCustomButton ()
@property (nonatomic, strong) UIImageView *imgView;
@property (nonatomic, strong) UILabel *btnNameLabel;
@end
@implementation HLYCustomButton
- (instancetype)initWithFrame:(CGRect)frame imgName:(NSString *)imgName titleString:(NSString *)title{
if(self = [super initWithFrame:frame]){
[self initSubViewsWithImgName:imgName title:title];
}
return self;
}
- (void)initSubViewsWithImgName:(NSString *)imgName title:(NSString *)title{
CGSize size = self.frame.size;
if(size.width == 0){
return;
}
_imgView = [[UIImageView alloc] initWithFrame:CGRectMake((size.width-kImgWidth)/2, 0, kImgWidth, kImgWidth)];
_imgView.image = [UIImage imageNamed:imgName];
[self addSubview:_imgView];
_btnNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_imgView.frame)+8, size.width, 25)];
_btnNameLabel.font = [UIFont fontWithName:title size:14];
_btnNameLabel.text = title;
_btnNameLabel.textAlignment = NSTextAlignmentCenter;
_btnNameLabel.textColor = [UIColor whiteColor];
[self addSubview:_btnNameLabel];
}
- (void)setClickTitle:(NSString *)title isOpen:(BOOL)isOpen{
dispatch_async(dispatch_get_main_queue(), ^{
_btnNameLabel.text = title;
if(isOpen){
_imgView.image = [UIImage imageNamed:@"light_open"];
_btnNameLabel.textColor = [UIColor colorWithRed:25/255.0f green:120/255.0f blue:209/255.0f alpha:1];
}else{
_btnNameLabel.textColor = [UIColor whiteColor];
_imgView.image = [UIImage imageNamed:@"light_close"];
}
});
}
@end
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
typedef enum : NSInteger {
NotReachable = 0,
ReachableViaWiFi,
ReachableViaWWAN
} NetworkStatus;
#pragma mark IPv6 Support
//Reachability fully support IPv6. For full details, see ReadMe.md.
extern NSString *kReachabilityChangedNotification;
@interface Reachability : NSObject
/*!
* Use to check the reachability of a given host name.
*/
+ (instancetype)reachabilityWithHostName:(NSString *)hostName;
/*!
* Use to check the reachability of a given IP address.
*/
+ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress;
/*!
* Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
*/
+ (instancetype)reachabilityForInternetConnection;
#pragma mark reachabilityForLocalWiFi
//reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information.
//+ (instancetype)reachabilityForLocalWiFi;
/*!
* Start listening for reachability notifications on the current run loop.
*/
- (BOOL)startNotifier;
- (void)stopNotifier;
- (NetworkStatus)currentReachabilityStatus;
/*!
* WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
*/
- (BOOL)connectionRequired;
@end
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
*/
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <CoreFoundation/CoreFoundation.h>
#import "Reachability.h"
#pragma mark IPv6 Support
//Reachability fully support IPv6. For full details, see ReadMe.md.
NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";
#pragma mark - Supporting functions
#define kShouldPrintReachabilityFlags 1
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
{
#if kShouldPrintReachabilityFlags
NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
comment
);
#endif
}
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target, flags)
NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
Reachability* noteObject = (__bridge Reachability *)info;
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
}
#pragma mark - Reachability implementation
@implementation Reachability
{
SCNetworkReachabilityRef _reachabilityRef;
}
+ (instancetype)reachabilityWithHostName:(NSString *)hostName
{
Reachability* returnValue = NULL;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
if (reachability != NULL)
{
returnValue= [[self alloc] init];
if (returnValue != NULL)
{
returnValue->_reachabilityRef = reachability;
}
else {
CFRelease(reachability);
}
}
return returnValue;
}
+ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, hostAddress);
Reachability* returnValue = NULL;
if (reachability != NULL)
{
returnValue = [[self alloc] init];
if (returnValue != NULL)
{
returnValue->_reachabilityRef = reachability;
}
else {
CFRelease(reachability);
}
}
return returnValue;
}
+ (instancetype)reachabilityForInternetConnection
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress];
}
#pragma mark reachabilityForLocalWiFi
//reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information.
//+ (instancetype)reachabilityForLocalWiFi
#pragma mark - Start and stop notifier
- (BOOL)startNotifier
{
BOOL returnValue = NO;
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
{
if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
{
returnValue = YES;
}
}
return returnValue;
}
- (void)stopNotifier
{
if (_reachabilityRef != NULL)
{
SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
}
- (void)dealloc
{
[self stopNotifier];
if (_reachabilityRef != NULL)
{
CFRelease(_reachabilityRef);
}
}
#pragma mark - Network Flag Handling
- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
{
PrintReachabilityFlags(flags, "networkStatusForFlags");
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
{
// The target host is not reachable.
return NotReachable;
}
NetworkStatus returnValue = NotReachable;
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
/*
If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
*/
returnValue = ReachableViaWiFi;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
/*
... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
*/
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
/*
... and no [user] intervention is needed...
*/
returnValue = ReachableViaWiFi;
}
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
/*
... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
*/
returnValue = ReachableViaWWAN;
}
return returnValue;
}
- (BOOL)connectionRequired
{
NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
{
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}
return NO;
}
- (NetworkStatus)currentReachabilityStatus
{
NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef");
NetworkStatus returnValue = NotReachable;
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
{
returnValue = [self networkStatusForFlags:flags];
}
return returnValue;
}
@end
//
// UIView+Toast.h
// Toast
//
// Copyright (c) 2011-2016 Charles Scalesse.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <UIKit/UIKit.h>
extern const NSString * CSToastPositionTop;
extern const NSString * CSToastPositionCenter;
extern const NSString * CSToastPositionBottom;
@class CSToastStyle;
/**
Toast is an Objective-C category that adds toast notifications to the UIView
object class. It is intended to be simple, lightweight, and easy to use. Most
toast notifications can be triggered with a single line of code.
The `makeToast:` methods create a new view and then display it as toast.
The `showToast:` methods display any view as toast.
*/
@interface UIView (Toast)
/**
Creates and presents a new toast view with a message and displays it with the
default duration and position. Styled using the shared style.
@param message The message to be displayed
*/
- (void)makeToast:(NSString *)message;
/**
Creates and presents a new toast view with a message. Duration and position
can be set explicitly. Styled using the shared style.
@param message The message to be displayed
@param duration The toast duration
@param position The toast's center point. Can be one of the predefined CSToastPosition
constants or a `CGPoint` wrapped in an `NSValue` object.
*/
- (void)makeToast:(NSString *)message
duration:(NSTimeInterval)duration
position:(id)position;
/**
Creates and presents a new toast view with a message. Duration, position, and
style can be set explicitly.
@param message The message to be displayed
@param duration The toast duration
@param position The toast's center point. Can be one of the predefined CSToastPosition
constants or a `CGPoint` wrapped in an `NSValue` object.
@param style The style. The shared style will be used when nil
*/
- (void)makeToast:(NSString *)message
duration:(NSTimeInterval)duration
position:(id)position
style:(CSToastStyle *)style;
/**
Creates and presents a new toast view with a message, title, and image. Duration,
position, and style can be set explicitly. The completion block executes when the
toast view completes. `didTap` will be `YES` if the toast view was dismissed from
a tap.
@param message The message to be displayed
@param duration The toast duration
@param position The toast's center point. Can be one of the predefined CSToastPosition
constants or a `CGPoint` wrapped in an `NSValue` object.
@param title The title
@param image The image
@param style The style. The shared style will be used when nil
@param completion The completion block, executed after the toast view disappears.
didTap will be `YES` if the toast view was dismissed from a tap.
*/
- (void)makeToast:(NSString *)message
duration:(NSTimeInterval)duration
position:(id)position
title:(NSString *)title
image:(UIImage *)image
style:(CSToastStyle *)style
completion:(void(^)(BOOL didTap))completion;
/**
Creates a new toast view with any combination of message, title, and image.
The look and feel is configured via the style. Unlike the `makeToast:` methods,
this method does not present the toast view automatically. One of the showToast:
methods must be used to present the resulting view.
@warning if message, title, and image are all nil, this method will return nil.
@param message The message to be displayed
@param title The title
@param image The image
@param style The style. The shared style will be used when nil
@return The newly created toast view
*/
- (UIView *)toastViewForMessage:(NSString *)message
title:(NSString *)title
image:(UIImage *)image
style:(CSToastStyle *)style;
/**
Dismisses all active toast views. Any toast that is currently being displayed on the
screen is considered active.
@warning this does not clear toast views that are currently waiting in the queue. The next queued
toast will appear immediately after `hideToasts` completes the dismissal animation.
*/
- (void)hideToasts;
/**
Dismisses an active toast view.
@param toast The active toast view to dismiss. Any toast that is currently being displayed
on the screen is considered active.
@warning this does not clear a toast view that is currently waiting in the queue.
*/
- (void)hideToast:(UIView *)toast;
/**
Creates and displays a new toast activity indicator view at a specified position.
@warning Only one toast activity indicator view can be presented per superview. Subsequent
calls to `makeToastActivity:` will be ignored until hideToastActivity is called.
@warning `makeToastActivity:` works independently of the showToast: methods. Toast activity
views can be presented and dismissed while toast views are being displayed. `makeToastActivity:`
has no effect on the queueing behavior of the showToast: methods.
@param position The toast's center point. Can be one of the predefined CSToastPosition
constants or a `CGPoint` wrapped in an `NSValue` object.
*/
- (void)makeToastActivity:(id)position;
/**
Dismisses the active toast activity indicator view.
*/
- (void)hideToastActivity;
/**
Displays any view as toast using the default duration and position.
@param toast The view to be displayed as toast
*/
- (void)showToast:(UIView *)toast;
/**
Displays any view as toast at a provided position and duration. The completion block
executes when the toast view completes. `didTap` will be `YES` if the toast view was
dismissed from a tap.
@param toast The view to be displayed as toast
@param duration The notification duration
@param position The toast's center point. Can be one of the predefined CSToastPosition
constants or a `CGPoint` wrapped in an `NSValue` object.
@param completion The completion block, executed after the toast view disappears.
didTap will be `YES` if the toast view was dismissed from a tap.
*/
- (void)showToast:(UIView *)toast
duration:(NSTimeInterval)duration
position:(id)position
completion:(void(^)(BOOL didTap))completion;
@end
/**
`CSToastStyle` instances define the look and feel for toast views created via the
`makeToast:` methods as well for toast views created directly with
`toastViewForMessage:title:image:style:`.
@warning `CSToastStyle` offers relatively simple styling options for the default
toast view. If you require a toast view with more complex UI, it probably makes more
sense to create your own custom UIView subclass and present it with the `showToast:`
methods.
*/
@interface CSToastStyle : NSObject
/**
The background color. Default is `[UIColor blackColor]` at 80% opacity.
*/
@property (strong, nonatomic) UIColor *backgroundColor;
/**
The title color. Default is `[UIColor whiteColor]`.
*/
@property (strong, nonatomic) UIColor *titleColor;
/**
The message color. Default is `[UIColor whiteColor]`.
*/
@property (strong, nonatomic) UIColor *messageColor;
/**
A percentage value from 0.0 to 1.0, representing the maximum width of the toast
view relative to it's superview. Default is 0.8 (80% of the superview's width).
*/
@property (assign, nonatomic) CGFloat maxWidthPercentage;
/**
A percentage value from 0.0 to 1.0, representing the maximum height of the toast
view relative to it's superview. Default is 0.8 (80% of the superview's height).
*/
@property (assign, nonatomic) CGFloat maxHeightPercentage;
/**
The spacing from the horizontal edge of the toast view to the content. When an image
is present, this is also used as the padding between the image and the text.
Default is 10.0.
*/
@property (assign, nonatomic) CGFloat horizontalPadding;
/**
The spacing from the vertical edge of the toast view to the content. When a title
is present, this is also used as the padding between the title and the message.
Default is 10.0.
*/
@property (assign, nonatomic) CGFloat verticalPadding;
/**
The corner radius. Default is 10.0.
*/
@property (assign, nonatomic) CGFloat cornerRadius;
/**
The title font. Default is `[UIFont boldSystemFontOfSize:16.0]`.
*/
@property (strong, nonatomic) UIFont *titleFont;
/**
The message font. Default is `[UIFont systemFontOfSize:16.0]`.
*/
@property (strong, nonatomic) UIFont *messageFont;
/**
The title text alignment. Default is `NSTextAlignmentLeft`.
*/
@property (assign, nonatomic) NSTextAlignment titleAlignment;
/**
The message text alignment. Default is `NSTextAlignmentLeft`.
*/
@property (assign, nonatomic) NSTextAlignment messageAlignment;
/**
The maximum number of lines for the title. The default is 0 (no limit).
*/
@property (assign, nonatomic) NSInteger titleNumberOfLines;
/**
The maximum number of lines for the message. The default is 0 (no limit).
*/
@property (assign, nonatomic) NSInteger messageNumberOfLines;
/**
Enable or disable a shadow on the toast view. Default is `NO`.
*/
@property (assign, nonatomic) BOOL displayShadow;
/**
The shadow color. Default is `[UIColor blackColor]`.
*/
@property (strong, nonatomic) UIColor *shadowColor;
/**
A value from 0.0 to 1.0, representing the opacity of the shadow.
Default is 0.8 (80% opacity).
*/
@property (assign, nonatomic) CGFloat shadowOpacity;
/**
The shadow radius. Default is 6.0.
*/
@property (assign, nonatomic) CGFloat shadowRadius;
/**
The shadow offset. The default is `CGSizeMake(4.0, 4.0)`.
*/
@property (assign, nonatomic) CGSize shadowOffset;
/**
The image size. The default is `CGSizeMake(80.0, 80.0)`.
*/
@property (assign, nonatomic) CGSize imageSize;
/**
The size of the toast activity view when `makeToastActivity:` is called.
Default is `CGSizeMake(100.0, 100.0)`.
*/
@property (assign, nonatomic) CGSize activitySize;
/**
The fade in/out animation duration. Default is 0.2.
*/
@property (assign, nonatomic) NSTimeInterval fadeDuration;
/**
Creates a new instance of `CSToastStyle` with all the default values set.
*/
- (instancetype)initWithDefaultStyle NS_DESIGNATED_INITIALIZER;
/**
@warning Only the designated initializer should be used to create
an instance of `CSToastStyle`.
*/
- (instancetype)init NS_UNAVAILABLE;
@end
/**
`CSToastManager` provides general configuration options for all toast
notifications. Backed by a singleton instance.
*/
@interface CSToastManager : NSObject
/**
Sets the shared style on the singleton. The shared style is used whenever
a `makeToast:` method (or `toastViewForMessage:title:image:style:`) is called
with with a nil style. By default, this is set to `CSToastStyle`'s default
style.
@param sharedStyle the shared style
*/
+ (void)setSharedStyle:(CSToastStyle *)sharedStyle;
/**
Gets the shared style from the singlton. By default, this is
`CSToastStyle`'s default style.
@return the shared style
*/
+ (CSToastStyle *)sharedStyle;
/**
Enables or disables tap to dismiss on toast views. Default is `YES`.
@param tapToDismissEnabled YES or NO
*/
+ (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled;
/**
Returns `YES` if tap to dismiss is enabled, otherwise `NO`.
Default is `YES`.
@return BOOL YES or NO
*/
+ (BOOL)isTapToDismissEnabled;
/**
Enables or disables queueing behavior for toast views. When `YES`,
toast views will appear one after the other. When `NO`, multiple Toast
views will appear at the same time (potentially overlapping depending
on their positions). This has no effect on the toast activity view,
which operates independently of normal toast views. Default is `YES`.
@param queueEnabled YES or NO
*/
+ (void)setQueueEnabled:(BOOL)queueEnabled;
/**
Returns `YES` if the queue is enabled, otherwise `NO`.
Default is `YES`.
@return BOOL
*/
+ (BOOL)isQueueEnabled;
/**
Sets the default duration. Used for the `makeToast:` and
`showToast:` methods that don't require an explicit duration.
Default is 3.0.
@param duration The toast duration
*/
+ (void)setDefaultDuration:(NSTimeInterval)duration;
/**
Returns the default duration. Default is 3.0.
@return duration The toast duration
*/
+ (NSTimeInterval)defaultDuration;
/**
Sets the default position. Used for the `makeToast:` and
`showToast:` methods that don't require an explicit position.
Default is `CSToastPositionBottom`.
@param position The default center point. Can be one of the predefined
CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object.
*/
+ (void)setDefaultPosition:(id)position;
/**
Returns the default toast position. Default is `CSToastPositionBottom`.
@return position The default center point. Will be one of the predefined
CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object.
*/
+ (id)defaultPosition;
@end
//
// UIView+Toast.m
// Toast
//
// Copyright (c) 2011-2016 Charles Scalesse.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "UIView+Toast.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
NSString * CSToastPositionTop = @"CSToastPositionTop";
NSString * CSToastPositionCenter = @"CSToastPositionCenter";
NSString * CSToastPositionBottom = @"CSToastPositionBottom";
// Keys for values associated with toast views
static const NSString * CSToastTimerKey = @"CSToastTimerKey";
static const NSString * CSToastDurationKey = @"CSToastDurationKey";
static const NSString * CSToastPositionKey = @"CSToastPositionKey";
static const NSString * CSToastCompletionKey = @"CSToastCompletionKey";
// Keys for values associated with self
static const NSString * CSToastActiveKey = @"CSToastActiveKey";
static const NSString * CSToastActivityViewKey = @"CSToastActivityViewKey";
static const NSString * CSToastQueueKey = @"CSToastQueueKey";
@interface UIView (ToastPrivate)
/**
These private methods are being prefixed with "cs_" to reduce the likelihood of non-obvious
naming conflicts with other UIView methods.
@discussion Should the public API also use the cs_ prefix? Technically it should, but it
results in code that is less legible. The current public method names seem unlikely to cause
conflicts so I think we should favor the cleaner API for now.
*/
- (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position;
- (void)cs_hideToast:(UIView *)toast;
- (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap;
- (void)cs_toastTimerDidFinish:(NSTimer *)timer;
- (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer;
- (CGPoint)cs_centerPointForPosition:(id)position withToast:(UIView *)toast;
- (NSMutableArray *)cs_toastQueue;
@end
@implementation UIView (Toast)
#pragma mark - Make Toast Methods
- (void)makeToast:(NSString *)message {
[self makeToast:message duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] style:nil];
}
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position {
[self makeToast:message duration:duration position:position style:nil];
}
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position style:(CSToastStyle *)style {
UIView *toast = [self toastViewForMessage:message title:nil image:nil style:style];
[self showToast:toast duration:duration position:position completion:nil];
}
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style completion:(void(^)(BOOL didTap))completion {
UIView *toast = [self toastViewForMessage:message title:title image:image style:style];
[self showToast:toast duration:duration position:position completion:completion];
}
#pragma mark - Show Toast Methods
- (void)showToast:(UIView *)toast {
[self showToast:toast duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] completion:nil];
}
- (void)showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position completion:(void(^)(BOOL didTap))completion {
// sanity
if (toast == nil) return;
// store the completion block on the toast view
objc_setAssociatedObject(toast, &CSToastCompletionKey, completion, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if ([CSToastManager isQueueEnabled] && [self.cs_activeToasts count] > 0) {
// we're about to queue this toast view so we need to store the duration and position as well
objc_setAssociatedObject(toast, &CSToastDurationKey, @(duration), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(toast, &CSToastPositionKey, position, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// enqueue
[self.cs_toastQueue addObject:toast];
} else {
// present
[self cs_showToast:toast duration:duration position:position];
}
}
#pragma mark - Hide Toast Method
- (void)hideToasts {
for (UIView *toast in [self cs_activeToasts]) {
[self hideToast:toast];
}
}
- (void)hideToast:(UIView *)toast {
// sanity
if (!toast || ![[self cs_activeToasts] containsObject:toast]) return;
NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey);
[timer invalidate];
[self cs_hideToast:toast];
}
#pragma mark - Private Show/Hide Methods
- (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position {
toast.center = [self cs_centerPointForPosition:position withToast:toast];
toast.alpha = 0.0;
if ([CSToastManager isTapToDismissEnabled]) {
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cs_handleToastTapped:)];
[toast addGestureRecognizer:recognizer];
toast.userInteractionEnabled = YES;
toast.exclusiveTouch = YES;
}
[[self cs_activeToasts] addObject:toast];
[self addSubview:toast];
[UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration]
delay:0.0
options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction)
animations:^{
toast.alpha = 1.0;
} completion:^(BOOL finished) {
NSTimer *timer = [NSTimer timerWithTimeInterval:duration target:self selector:@selector(cs_toastTimerDidFinish:) userInfo:toast repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
objc_setAssociatedObject(toast, &CSToastTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}];
}
- (void)cs_hideToast:(UIView *)toast {
[self cs_hideToast:toast fromTap:NO];
}
- (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap {
[UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration]
delay:0.0
options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState)
animations:^{
toast.alpha = 0.0;
} completion:^(BOOL finished) {
[toast removeFromSuperview];
// remove
[[self cs_activeToasts] removeObject:toast];
// execute the completion block, if necessary
void (^completion)(BOOL didTap) = objc_getAssociatedObject(toast, &CSToastCompletionKey);
if (completion) {
completion(fromTap);
}
if ([self.cs_toastQueue count] > 0) {
// dequeue
UIView *nextToast = [[self cs_toastQueue] firstObject];
[[self cs_toastQueue] removeObjectAtIndex:0];
// present the next toast
NSTimeInterval duration = [objc_getAssociatedObject(nextToast, &CSToastDurationKey) doubleValue];
id position = objc_getAssociatedObject(nextToast, &CSToastPositionKey);
[self cs_showToast:nextToast duration:duration position:position];
}
}];
}
#pragma mark - View Construction
- (UIView *)toastViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style {
// sanity
if(message == nil && title == nil && image == nil) return nil;
// default to the shared style
if (style == nil) {
style = [CSToastManager sharedStyle];
}
// dynamically build a toast view with any combination of message, title, & image
UILabel *messageLabel = nil;
UILabel *titleLabel = nil;
UIImageView *imageView = nil;
UIView *wrapperView = [[UIView alloc] init];
wrapperView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
wrapperView.layer.cornerRadius = style.cornerRadius;
if (style.displayShadow) {
wrapperView.layer.shadowColor = style.shadowColor.CGColor;
wrapperView.layer.shadowOpacity = style.shadowOpacity;
wrapperView.layer.shadowRadius = style.shadowRadius;
wrapperView.layer.shadowOffset = style.shadowOffset;
}
wrapperView.backgroundColor = style.backgroundColor;
if(image != nil) {
imageView = [[UIImageView alloc] initWithImage:image];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.frame = CGRectMake(style.horizontalPadding, style.verticalPadding, style.imageSize.width, style.imageSize.height);
}
CGRect imageRect = CGRectZero;
if(imageView != nil) {
imageRect.origin.x = style.horizontalPadding;
imageRect.origin.y = style.verticalPadding;
imageRect.size.width = imageView.bounds.size.width;
imageRect.size.height = imageView.bounds.size.height;
}
if (title != nil) {
titleLabel = [[UILabel alloc] init];
titleLabel.numberOfLines = style.titleNumberOfLines;
titleLabel.font = style.titleFont;
titleLabel.textAlignment = style.titleAlignment;
titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
titleLabel.textColor = style.titleColor;
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.alpha = 1.0;
titleLabel.text = title;
// size the title label according to the length of the text
CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage);
CGSize expectedSizeTitle = [titleLabel sizeThatFits:maxSizeTitle];
// UILabel can return a size larger than the max size when the number of lines is 1
expectedSizeTitle = CGSizeMake(MIN(maxSizeTitle.width, expectedSizeTitle.width), MIN(maxSizeTitle.height, expectedSizeTitle.height));
titleLabel.frame = CGRectMake(0.0, 0.0, expectedSizeTitle.width, expectedSizeTitle.height);
}
if (message != nil) {
messageLabel = [[UILabel alloc] init];
messageLabel.numberOfLines = style.messageNumberOfLines;
messageLabel.font = style.messageFont;
messageLabel.textAlignment = style.messageAlignment;
messageLabel.lineBreakMode = NSLineBreakByTruncatingTail;
messageLabel.textColor = style.messageColor;
messageLabel.backgroundColor = [UIColor clearColor];
messageLabel.alpha = 1.0;
messageLabel.text = message;
CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage);
CGSize expectedSizeMessage = [messageLabel sizeThatFits:maxSizeMessage];
// UILabel can return a size larger than the max size when the number of lines is 1
expectedSizeMessage = CGSizeMake(MIN(maxSizeMessage.width, expectedSizeMessage.width), MIN(maxSizeMessage.height, expectedSizeMessage.height));
messageLabel.frame = CGRectMake(0.0, 0.0, expectedSizeMessage.width, expectedSizeMessage.height);
}
CGRect titleRect = CGRectZero;
if(titleLabel != nil) {
titleRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding;
titleRect.origin.y = style.verticalPadding;
titleRect.size.width = titleLabel.bounds.size.width;
titleRect.size.height = titleLabel.bounds.size.height;
}
CGRect messageRect = CGRectZero;
if(messageLabel != nil) {
messageRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding;
messageRect.origin.y = titleRect.origin.y + titleRect.size.height + style.verticalPadding;
messageRect.size.width = messageLabel.bounds.size.width;
messageRect.size.height = messageLabel.bounds.size.height;
}
CGFloat longerWidth = MAX(titleRect.size.width, messageRect.size.width);
CGFloat longerX = MAX(titleRect.origin.x, messageRect.origin.x);
// Wrapper width uses the longerWidth or the image width, whatever is larger. Same logic applies to the wrapper height.
CGFloat wrapperWidth = MAX((imageRect.size.width + (style.horizontalPadding * 2.0)), (longerX + longerWidth + style.horizontalPadding));
CGFloat wrapperHeight = MAX((messageRect.origin.y + messageRect.size.height + style.verticalPadding), (imageRect.size.height + (style.verticalPadding * 2.0)));
wrapperView.frame = CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight);
if(titleLabel != nil) {
titleLabel.frame = titleRect;
[wrapperView addSubview:titleLabel];
}
if(messageLabel != nil) {
messageLabel.frame = messageRect;
[wrapperView addSubview:messageLabel];
}
if(imageView != nil) {
[wrapperView addSubview:imageView];
}
return wrapperView;
}
#pragma mark - Storage
- (NSMutableArray *)cs_activeToasts {
NSMutableArray *cs_activeToasts = objc_getAssociatedObject(self, &CSToastActiveKey);
if (cs_activeToasts == nil) {
cs_activeToasts = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, &CSToastActiveKey, cs_activeToasts, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return cs_activeToasts;
}
- (NSMutableArray *)cs_toastQueue {
NSMutableArray *cs_toastQueue = objc_getAssociatedObject(self, &CSToastQueueKey);
if (cs_toastQueue == nil) {
cs_toastQueue = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, &CSToastQueueKey, cs_toastQueue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return cs_toastQueue;
}
#pragma mark - Events
- (void)cs_toastTimerDidFinish:(NSTimer *)timer {
[self cs_hideToast:(UIView *)timer.userInfo];
}
- (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer {
UIView *toast = recognizer.view;
NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey);
[timer invalidate];
[self cs_hideToast:toast fromTap:YES];
}
#pragma mark - Activity Methods
- (void)makeToastActivity:(id)position {
// sanity
UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey);
if (existingActivityView != nil) return;
CSToastStyle *style = [CSToastManager sharedStyle];
UIView *activityView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, style.activitySize.width, style.activitySize.height)];
activityView.center = [self cs_centerPointForPosition:position withToast:activityView];
activityView.backgroundColor = style.backgroundColor;
activityView.alpha = 0.0;
activityView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
activityView.layer.cornerRadius = style.cornerRadius;
if (style.displayShadow) {
activityView.layer.shadowColor = style.shadowColor.CGColor;
activityView.layer.shadowOpacity = style.shadowOpacity;
activityView.layer.shadowRadius = style.shadowRadius;
activityView.layer.shadowOffset = style.shadowOffset;
}
UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityIndicatorView.center = CGPointMake(activityView.bounds.size.width / 2, activityView.bounds.size.height / 2);
[activityView addSubview:activityIndicatorView];
[activityIndicatorView startAnimating];
// associate the activity view with self
objc_setAssociatedObject (self, &CSToastActivityViewKey, activityView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self addSubview:activityView];
[UIView animateWithDuration:style.fadeDuration
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
activityView.alpha = 1.0;
} completion:nil];
}
- (void)hideToastActivity {
UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey);
if (existingActivityView != nil) {
[UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration]
delay:0.0
options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState)
animations:^{
existingActivityView.alpha = 0.0;
} completion:^(BOOL finished) {
[existingActivityView removeFromSuperview];
objc_setAssociatedObject (self, &CSToastActivityViewKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}];
}
}
#pragma mark - Helpers
- (CGPoint)cs_centerPointForPosition:(id)point withToast:(UIView *)toast {
CSToastStyle *style = [CSToastManager sharedStyle];
if([point isKindOfClass:[NSString class]]) {
if([point caseInsensitiveCompare:CSToastPositionTop] == NSOrderedSame) {
return CGPointMake(self.bounds.size.width/2, (toast.frame.size.height / 2) + style.verticalPadding);
} else if([point caseInsensitiveCompare:CSToastPositionCenter] == NSOrderedSame) {
return CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
}
} else if ([point isKindOfClass:[NSValue class]]) {
return [point CGPointValue];
}
// default to bottom
return CGPointMake(self.bounds.size.width/2, (self.bounds.size.height - (toast.frame.size.height / 2)) - style.verticalPadding);
}
@end
@implementation CSToastStyle
#pragma mark - Constructors
- (instancetype)initWithDefaultStyle {
self = [super init];
if (self) {
self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8];
self.titleColor = [UIColor whiteColor];
self.messageColor = [UIColor whiteColor];
self.maxWidthPercentage = 0.8;
self.maxHeightPercentage = 0.8;
self.horizontalPadding = 10.0;
self.verticalPadding = 10.0;
self.cornerRadius = 10.0;
self.titleFont = [UIFont boldSystemFontOfSize:16.0];
self.messageFont = [UIFont systemFontOfSize:16.0];
self.titleAlignment = NSTextAlignmentLeft;
self.messageAlignment = NSTextAlignmentLeft;
self.titleNumberOfLines = 0;
self.messageNumberOfLines = 0;
self.displayShadow = NO;
self.shadowOpacity = 0.8;
self.shadowRadius = 6.0;
self.shadowOffset = CGSizeMake(4.0, 4.0);
self.imageSize = CGSizeMake(80.0, 80.0);
self.activitySize = CGSizeMake(100.0, 100.0);
self.fadeDuration = 0.2;
}
return self;
}
- (void)setMaxWidthPercentage:(CGFloat)maxWidthPercentage {
_maxWidthPercentage = MAX(MIN(maxWidthPercentage, 1.0), 0.0);
}
- (void)setMaxHeightPercentage:(CGFloat)maxHeightPercentage {
_maxHeightPercentage = MAX(MIN(maxHeightPercentage, 1.0), 0.0);
}
- (instancetype)init NS_UNAVAILABLE {
return nil;
}
@end
@interface CSToastManager ()
@property (strong, nonatomic) CSToastStyle *sharedStyle;
@property (assign, nonatomic, getter=isTapToDismissEnabled) BOOL tapToDismissEnabled;
@property (assign, nonatomic, getter=isQueueEnabled) BOOL queueEnabled;
@property (assign, nonatomic) NSTimeInterval defaultDuration;
@property (strong, nonatomic) id defaultPosition;
@end
@implementation CSToastManager
#pragma mark - Constructors
+ (instancetype)sharedManager {
static CSToastManager *_sharedManager = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedManager = [[self alloc] init];
});
return _sharedManager;
}
- (instancetype)init {
self = [super init];
if (self) {
self.sharedStyle = [[CSToastStyle alloc] initWithDefaultStyle];
self.tapToDismissEnabled = YES;
self.queueEnabled = YES;
self.defaultDuration = 3.0;
self.defaultPosition = CSToastPositionBottom;
}
return self;
}
#pragma mark - Singleton Methods
+ (void)setSharedStyle:(CSToastStyle *)sharedStyle {
[[self sharedManager] setSharedStyle:sharedStyle];
}
+ (CSToastStyle *)sharedStyle {
return [[self sharedManager] sharedStyle];
}
+ (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled {
[[self sharedManager] setTapToDismissEnabled:tapToDismissEnabled];
}
+ (BOOL)isTapToDismissEnabled {
return [[self sharedManager] isTapToDismissEnabled];
}
+ (void)setQueueEnabled:(BOOL)queueEnabled {
[[self sharedManager] setQueueEnabled:queueEnabled];
}
+ (BOOL)isQueueEnabled {
return [[self sharedManager] isQueueEnabled];
}
+ (void)setDefaultDuration:(NSTimeInterval)duration {
[[self sharedManager] setDefaultDuration:duration];
}
+ (NSTimeInterval)defaultDuration {
return [[self sharedManager] defaultDuration];
}
+ (void)setDefaultPosition:(id)position {
if ([position isKindOfClass:[NSString class]] || [position isKindOfClass:[NSValue class]]) {
[[self sharedManager] setDefaultPosition:position];
}
}
+ (id)defaultPosition {
return [[self sharedManager] defaultPosition];
}
@end
var exec = require('cordova/exec');
module.exports = {
startScan: function (scannerSubtitle, successCallback, errorCallback) {
exec(successCallback, errorCallback, "Barcode", "startScan", [scannerSubtitle]);
},
hasPermission: function (successCallback, errorCallback) {
exec(successCallback, errorCallback, "Barcode", "hasPermission", []);
}
};
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