<edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
<string>APP需要使用您的相册权限,没有该权限将无法完成扫一扫功能</string>
</edit-config>
-
<feature name="CDVWKWebViewEngine">
- <param name="ios-package" value="CDVWKWebViewEngine" />
+ <param name="ios-package" value="CDVWKWebViewEngine" />
</feature>
-
- <plugin name="cordova-plugin-fingerprint-aio" spec="~1.7.0">
- <variable name="FACEID_USAGE_DESCRIPTION" value="认证中..." />
- </plugin>
<plugin name="cordova-plugin-touch-id" spec="~3.3.1">
<variable name="FACEID_USAGE_DESCRIPTION" value=" " />
</plugin>
"integrity": "sha1-SWBrjBWlaI1HKPkuSnMloGHeB/U="
},
"cordova-plugin-fingerprint-aio": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/cordova-plugin-fingerprint-aio/-/cordova-plugin-fingerprint-aio-1.7.0.tgz",
- "integrity": "sha512-pV+JUeEhZUP85nXs9KMpHRClZppVHnpZA5h+8ReKBi4AV4vnzAcpUDBgFN7g3Ra83zmREYI/MqrlZlXn16pg3g==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-fingerprint-aio/-/cordova-plugin-fingerprint-aio-3.0.1.tgz",
+ "integrity": "sha512-Sgbv8Ykk74Ov1foEZg77owIqmHZoGktsv41rmW8KAAMf2JE93AawvQdUCYYROnk+ozG3D9ItELa5yhYU8i7Zhw==",
"requires": {
"cordova-plugin-add-swift-support": "^2.0.2"
}
"integrity": "sha1-jgOPbdsUvXZa4fS1IW4SCUUR4NA="
},
"semver": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz",
- "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ=="
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
},
"send": {
"version": "0.17.1",
"cordova-plugin-device": "^2.0.2",
"cordova-plugin-disable-ios11-statusbar": "^1.0.0",
"cordova-plugin-file": "^6.0.1",
- "cordova-plugin-fingerprint-aio": "^1.7.0",
+ "cordova-plugin-fingerprint-aio": "3.0.1",
"cordova-plugin-inappbrowser": "^3.0.0",
"cordova-plugin-jcore": "^1.3.0",
"cordova-plugin-qrscanner": "^3.0.1",
},
"cordova": {
"plugins": {
- "cordova-plugin-fingerprint-aio": {
- "FACEID_USAGE_DESCRIPTION": "认证中..."
- },
"cordova-plugin-touch-id": {},
"cordova-plugin-whitelist": {},
"cordova-plugin-advanced-http": {
"cordova-plugin-app-version": {},
"cordova-plugin-wkwebview-engine": {},
"cordova-plugin-brightness": {},
- "cordova-plugin-file": {}
+ "cordova-plugin-file": {},
+ "cordova-plugin-fingerprint-aio": {
+ "FACEID_USAGE_DESCRIPTION": " "
+ }
},
"platforms": [
"android",
"res/xml/config.xml": {
"parents": {
"/*": [
- {
- "xml": "<feature name=\"Fingerprint\"><param name=\"android-package\" value=\"de.niklasmerz.cordova.fingerprint.Fingerprint\" /></feature>",
- "count": 1
- },
{
"xml": "<feature name=\"Whitelist\"><param name=\"android-package\" value=\"org.apache.cordova.whitelist.WhitelistPlugin\" /><param name=\"onload\" value=\"true\" /></feature>",
"count": 1
{
"xml": "<feature name=\"Brightness\"><param name=\"android-package\" value=\"org.apache.cordova.plugin.Brightness.BrightnessPlugin\" /></feature>",
"count": 1
+ },
+ {
+ "xml": "<feature name=\"Fingerprint\"><param name=\"android-package\" value=\"de.niklasmerz.cordova.biometric.Fingerprint\" /></feature>",
+ "count": 1
}
]
}
"AndroidManifest.xml": {
"parents": {
"/*": [
- {
- "xml": "<uses-permission android:name=\"android.permission.USE_FINGERPRINT\" />",
- "count": 1
- },
{
"xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />",
"count": 2
{
"xml": "<uses-feature android:name=\"android.hardware.camera.front\" android:required=\"false\" />",
"count": 1
+ },
+ {
+ "xml": "<uses-permission android:name=\"android.permission.USE_BIOMETRIC\" />",
+ "count": 1
+ },
+ {
+ "xml": "<uses-permission android:name=\"android.permission.USE_FINGERPRINT\" />",
+ "count": 1
}
],
"/manifest": [
{
"xml": "<meta-data android:name=\"JPUSH_APPKEY\" android:value=\"d644d997f2cab0551ff704a3\" />",
"count": 1
+ },
+ {
+ "xml": "<activity android:exported=\"true\" android:name=\"de.niklasmerz.cordova.biometric.BiometricActivity\" android:theme=\"@style/TransparentTheme\" />",
+ "count": 1
}
]
}
"cordova-plugin-add-swift-support": {
"PACKAGE_NAME": "com.dalicitycard.app"
},
- "cordova-plugin-fingerprint-aio": {
- "PACKAGE_NAME": "com.dalicitycard.app"
- },
"cordova-plugin-touch-id": {
"PACKAGE_NAME": "com.dalicitycard.app"
},
},
"cordova-plugin-brightness": {
"PACKAGE_NAME": "com.dalicitycard.app"
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "PACKAGE_NAME": "com.dalicitycard.app"
}
},
"dependent_plugins": {},
"modules": [
- {
- "id": "cordova-plugin-fingerprint-aio.Fingerprint",
- "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
- "pluginId": "cordova-plugin-fingerprint-aio",
- "clobbers": [
- "Fingerprint"
- ]
- },
{
"id": "cordova-plugin-touch-id.TouchID",
"file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
"clobbers": [
"cordova.plugins.brightness"
]
+ },
+ {
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "pluginId": "cordova-plugin-fingerprint-aio",
+ "clobbers": [
+ "Fingerprint"
+ ]
}
],
"plugin_metadata": {
"cordova-plugin-add-swift-support": "2.0.2",
- "cordova-plugin-fingerprint-aio": "1.7.0",
"cordova-plugin-touch-id": "3.3.1",
"cordova-plugin-whitelist": "1.3.3",
"cordova-plugin-file": "6.0.1",
"jpush-phonegap-plugin": "3.7.2",
"cordova-plugin-app-version": "0.1.9",
"cordova-plugin-wkwebview-engine": "1.2.1",
- "cordova-plugin-brightness": "0.1.5"
+ "cordova-plugin-brightness": "0.1.5",
+ "cordova-plugin-fingerprint-aio": "3.0.1"
}
}
// PLUGIN GRADLE EXTENSIONS START
apply from: "../cordova-plugin-qrscanner/dlapp-qrscanner.gradle"
+apply from: "../cordova-plugin-fingerprint-aio/app-build.gradle"
// PLUGIN GRADLE EXTENSIONS END
def hasBuildExtras1 = file('build-extras.gradle').exists()
}
versionCode 12
versionName '1.3.8'
- targetSdkVersion 26
+ targetSdkVersion 28
}
lintOptions {
abortOnError false
}
- compileSdkVersion 26
+ compileSdkVersion 28
buildToolsVersion '28.0.3'
// This code exists for Crosswalk and other Native APIs.
// By default, we multiply the existing version code in the
</receiver>
<meta-data android:name="JPUSH_CHANNEL" android:value="developer-default" />
<meta-data android:name="JPUSH_APPKEY" android:value="d644d997f2cab0551ff704a3" />
+ <activity android:exported="true" android:name="de.niklasmerz.cordova.biometric.BiometricActivity" android:theme="@style/TransparentTheme" />
</application>
- <uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.USE_BIOMETRIC" />
+ <uses-permission android:name="android.permission.USE_FINGERPRINT" />
</manifest>
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
- {
- "id": "cordova-plugin-fingerprint-aio.Fingerprint",
- "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
- "pluginId": "cordova-plugin-fingerprint-aio",
- "clobbers": [
- "Fingerprint"
- ]
- },
{
"id": "cordova-plugin-touch-id.TouchID",
"file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
]
},
{
- "id": "cordova-plugin-file-opener2.FileOpener2",
- "file": "plugins/cordova-plugin-file-opener2/www/plugins.FileOpener2.js",
- "pluginId": "cordova-plugin-file-opener2",
- "clobbers": [
- "cordova.plugins.fileOpener2"
- ]
- },
- {
- "id": "cordova-plugin-file-transfer.FileTransferError",
- "file": "plugins/cordova-plugin-file-transfer/www/FileTransferError.js",
- "pluginId": "cordova-plugin-file-transfer",
- "clobbers": [
- "window.FileTransferError"
- ]
- },
- {
- "id": "cordova-plugin-file-transfer.FileTransfer",
- "file": "plugins/cordova-plugin-file-transfer/www/FileTransfer.js",
- "pluginId": "cordova-plugin-file-transfer",
- "clobbers": [
- "window.FileTransfer"
- ]
- },
- {
- "id": "cordova-plugin-crop.CropPlugin",
- "file": "plugins/cordova-plugin-crop/www/crop.js",
- "pluginId": "cordova-plugin-crop",
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "pluginId": "cordova-plugin-fingerprint-aio",
"clobbers": [
- "plugins.crop"
+ "Fingerprint"
]
}
];
module.exports.metadata = {
"cordova-plugin-add-swift-support": "2.0.2",
- "cordova-plugin-fingerprint-aio": "1.7.0",
"cordova-plugin-touch-id": "3.3.1",
"cordova-plugin-whitelist": "1.3.3",
"cordova-plugin-file": "6.0.1",
"cordova-plugin-app-version": "0.1.9",
"cordova-plugin-wkwebview-engine": "1.2.1",
"cordova-plugin-brightness": "0.1.5",
- "cordova-plugin-file-opener2": "2.2.1",
- "cordova-plugin-file-transfer": "1.7.1",
- "cordova-plugin-crop": "0.3.1"
+ "cordova-plugin-fingerprint-aio": "3.0.1"
};
});
\ No newline at end of file
window.localStorage.setItem("idno", idno);
window.localStorage.setItem("phoneX",ret.phonex);
window.localStorage.setItem("personid", ret.personid);
+ window.localStorage.setItem("userid", ret.personid);
window.localStorage.setItem("signed", ret.signed);
window.localStorage.setItem("paypwdset", ret.paypwdset);
- window.location = "bindcheck.html";
+ if(ret.signed=='yes'){
+ window.location = "main.html"
+ }else{
+ window.location = "bindcheck.html";
+ }
+
} else {
if (ret.code == -1) {
$.alert(ret.msg, "提示", function() {
onDeviceReady: function() {
this.receivedEvent('deviceready');
+ this.loginWithFinger();
+ },
+ loginWithFinger:function(){
+ let loginfinger = window.localStorage.getItem("loginfinger");
+ let phone = window.localStorage.getItem("phone");
+ let pwd = window.localStorage.getItem("localpwd");
+ let _this = this;
+ if(phone&&pwd&&loginfinger&&loginfinger=='1'){
+ Fingerprint.isAvailable(function(result){
+ Fingerprint.show({
+ title:"正在使用指纹或人脸登录",
+ description: "请验证您的指纹或人脸"
+ }, function(success){
+ _this.loginIt(phone,pwd);
+ }, function(error){
+ $.alert("验证失败,指纹或人脸错误,请使用密码登录", "提示");
+ //$("#login").removeAttr("checked");
+ });
+
+ }, function(message){
+ $.alert("设备不支持指纹或人脸,请使用密码登录", "提示");
+ });
+ }
},
// Update DOM on a Received Event
if(isEmpty(phone)||isEmpty(pwd)){
return;
}
- //loadingElement('loginBtn', '登录中...')
+ this.loginIt(phone,pwd);
+ },
+ loginIt: function(phone,pwd){
$.showLoading("登录中");
var param={
"username":phone,
window.localStorage.setItem("signed",ret.signed);
window.localStorage.setItem("paypwdset",ret.paypwdset);
window.localStorage.setItem("name",ret.name);
+ window.localStorage.setItem("localpwd",pwd);
window.location = "main.html";
}
}else{
})
})
});
+ $('#accsignbtn').click(function() {
+ app.checkBefore(function() {
+ var signed = window.localStorage.getItem("signed");
+ var cum = new auiDialog({});
+ if (isEmpty(signed) || signed != 'yes') {
+ var confirm = cum.alert({
+ title: "提示",
+ msg: '您尚未签约市民卡免密代扣签约协议,无法使用该功能',
+ buttons: ['取消', '去签约']
+ }, function(ret) {
+ if (ret.buttonIndex == 2) {
+ app.toSignCode();
+ }
+ })
+ }else{
+ window.location = 'signxycheck.html'
+ }
+ })
+ });
this.initData();
this.backBtn();
},
$("#loaddata").show()
$("#nodata").hide();
var param = {
- "pageno": 1
+ "pageno": 1,
+ "platform":"android"
}
V1Bills(param, function(ok, ret) {
if (ok) {
- //console.log(ret)
+ console.log(ret)
if (ret.code == 200) {
- app.checkVersion(ret.version,ret.minversion,ret.versionmsg);
+ //app.checkVersion(ret.version,ret.minversion,ret.versionmsg,ret.versionurl);
+ app.checkVersion("1.3.9","1","new func","https://shouji.baidu.com/software/26706357.html");
$("#maingt").text(ret.t + "!")
$("#user-amount").text(ret.amount)
$("#user-point").text(ret.point)
}
})
},
- checkVersion:function(ver,minver,msg){
+ checkVersion:function(ver,minver,m,url){
cordova.getAppVersion.getVersionNumber(function (version) {
//alert(version);
- if(version<minver){
- //TODO 强制升级
- alert("当前版本过低,为了不影响您的使用,请先升级");
- }else if(ver>version){
- alert("有新的版本");
+ alert(version);
+ if(ver>version){
+ var cum = new auiDialog({});
+ var confirm = cum.alert({
+ title: "有新的版本",
+ msg: m,
+ buttons: ['取消', '去更新']
+ }, function(ret) {
+ if (ret.buttonIndex == 2) {
+ cordova.InAppBrowser.open(url, '_system', 'location=no,toolbar=yes,toolbarposition=top,closebuttoncaption=关闭');
+ }
+ })
}
});
},
}
},
checkOther: function(callback) {
- var payseted = window.localStorage.getItem("paypwdset");
var signed = window.localStorage.getItem("signed");
var cum = new auiDialog({});
- console.log(payseted, signed)
- if (isEmpty(payseted) || !payseted || payseted != 'true') {
+
+ if (isEmpty(signed) || signed != 'yes') {
var confirm = cum.alert({
title: "提示",
- msg: '您还没有设置支付密码,无法使用该功能',
- buttons: ['取消', '去设置']
+ msg: '您尚未签约市民卡免密代扣签约协议,无法使用该功能',
+ buttons: ['取消', '去签约']
}, function(ret) {
if (ret.buttonIndex == 2) {
- window.location = 'paypwdset.html'
+ app.toSignCode();
}
})
} else {
- if (isEmpty(signed) || signed != 'yes') {
- var confirm = cum.alert({
- title: "提示",
- msg: '您尚未签约代扣免密付协议,无法使用该功能',
- buttons: ['取消', '去签约']
- }, function(ret) {
- if (ret.buttonIndex == 2) {
- window.location = 'signxy.html'
- }
- })
- } else {
- if (callback) {
- callback()
- }
+ if (callback) {
+ callback()
}
}
},
+ toSignCode: function(){
+ var param = {
+ }
+ V1Bindcardcode(param, function(ok, ret) {
+ if (ok) {
+ if (ret.code == 200) {
+ window.location = 'bindcheck.html'
+ } else {
+ $.alert(ret.msg, "错误");
+ }
+ } else {
+ $.alert("请求失败了 " + ret.status + ",请稍后再试", "错误");
+ }
+ })
+ },
toSign: function() {
window.location = 'signxycheck.html'
},
console.log(err);
});
}
+ document.addEventListener("backbutton", function(e){
+ e.preventDefault();
+ app.backTo();
+ }, false);
},
loadQrcode: function() {
$.showLoading("加载中");
if (ok) {
if (ret.code == 200) {
$.hideLoading();
+ $("#qrcode").html('');
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: ret.qrcode,
width: 200,
document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
},
onDeviceReady: function() {
+ let loginfinger = window.localStorage.getItem("loginfinger");
+ if(loginfinger&&loginfinger=='1'){
+ $("#login").prop("checked","checked");
+ }
},
editPwd: function() {
window.location = "editpwd.html";
},
toPayPwd: function() {
- window.location = "paypwdmng.html";
+ var payseted = window.localStorage.getItem("paypwdset");
+ if (isEmpty(payseted) || !payseted || payseted != 'true') {
+ window.location = 'paypwdset.html'
+ } else{
+ window.location = "paypwdmng.html";
+ }
},
logout:function(){
window.localStorage.removeItem("token");
window.location = "login.html";
},
loginByTouchId: function() {
- Fingerprint.isAvailable(function(result){
- alert("Fingerprint available");
- }, function(message){
- alert(message);
- });
+ let loginfinger = window.localStorage.getItem("loginfinger");
+ if(loginfinger&&loginfinger=='1'){
+ var confirm = new auiDialog({}).alert({
+ title: "提示",
+ msg: '确定关闭指纹或人脸登录吗?',
+ buttons: ['取消', '确定']
+ }, function(ret) {
+ if (ret.buttonIndex == 2) {
+ window.localStorage.setItem("loginfinger","0");
+ $("#login").removeAttr("checked");
+ }else{
+ //$("#login").attr("checked","checked");
+ }
+ });
+ }else{
+ let pwd = window.localStorage.getItem("localpwd");
+ if(!pwd){
+ $.alert("长时间未登录,需要先登录后再使用该功能", "提示",function(){
+ window.localStorage.removeItem("token");
+ window.location = "login.html";
+ });
+ return;
+ }
+ $("#login").removeAttr("checked");
+ Fingerprint.isAvailable(function(result){
+ Fingerprint.show({
+ title:"大理市民卡开启指纹或人脸登录",
+ description: "请验证您的指纹或人脸"
+ }, function(success){
+ window.localStorage.setItem("loginfinger","1");
+ $.alert("验证成功,您已开启指纹或人脸登录", "提示");
+ $("#login").prop("checked","checked");
+ }, function(error){
+ $.alert("验证失败,指纹或人脸错误次数过多,请稍后再试", "提示");
+ //$("#login").removeAttr("checked");
+ });
+
+ }, function(message){
+ $.alert("设备不支持指纹或人脸", "提示");
+ });
+ }
}
};
app.initialize();
if (dev) {
SERVER = "http://172.28.43.7:8099/payapi/mobileapi";
}
+function V1Bindcardcode(param,callback) {
+ ajaxPost("/v1/bindcardcode", param, callback)
+}
+
function V1Unbindcard(param,callback){
ajaxPost("/v1/unbindcard", param, callback)
}
if(ret.code==200){
$("#content").html(ret.page);
if(isEmpty(ret.signed)||ret.signed!='yes'){
- $("#btn").show();
- $("#content").css("bottom","135px");
+ //$("#btn").show();
+ //$("#content").css("bottom","135px");
}else{
- $("#content").css("bottom","10px");
+ //$("#content").css("bottom","10px");
}
}else{
$.alert(ret.msg, "错误");
<div class="aui-list-item-right" id="userbank"></div>
</div>
</li>
- <li class="aui-list-item" onclick="app.toSign()">
+ <li class="aui-list-item" id="accsignbtn">
<div class="aui-list-item-label-icon">
<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
</div>
cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) {
/*global cordova */
-function Fingerprint() {
-}
+var Fingerprint = function() {
+};
+
+// Plugin Errors
+Fingerprint.prototype.BIOMETRIC_UNKNOWN_ERROR = -100;
+Fingerprint.prototype.BIOMETRIC_UNAVAILABLE = -101;
+Fingerprint.prototype.BIOMETRIC_AUTHENTICATION_FAILED = -102;
+Fingerprint.prototype.BIOMETRIC_SDK_NOT_SUPPORTED = -103;
+Fingerprint.prototype.BIOMETRIC_HARDWARE_NOT_SUPPORTED = -104;
+Fingerprint.prototype.BIOMETRIC_PERMISSION_NOT_GRANTED = -105;
+Fingerprint.prototype.BIOMETRIC_NOT_ENROLLED = -106;
+Fingerprint.prototype.BIOMETRIC_INTERNAL_PLUGIN_ERROR = -107;
+Fingerprint.prototype.BIOMETRIC_DISMISSED = -108;
+Fingerprint.prototype.BIOMETRIC_PIN_OR_PATTERN_DISMISSED = -109;
+Fingerprint.prototype.BIOMETRIC_SCREEN_GUARD_UNSECURED = -110;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT = -111;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT_PERMANENT = -112;
+
+// Biometric types
+Fingerprint.prototype.BIOMETRIC_TYPE_FINGERPRINT = "finger";
+Fingerprint.prototype.BIOMETRIC_TYPE_FACE = "face";
+Fingerprint.prototype.BIOMETRIC_TYPE_COMMON = "biometric";
Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
cordova.exec(
<div style="background: #fff;text-align: center;" id="qrcode"></div>
</div>
<p style="text-align: center;margin-top:40px;color:#999">请将二维码对准扫描设备</p>
- <!--<div style="padding: 30px;">
- <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="window.location.reload();">刷新二维码</div>
- </div>-->
+ <div style="padding: 30px;">
+ <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.refresh()">刷新二维码</div>
+ </div>
</body>
</html>
<script type="text/javascript" src="cordova.js"></script>
<div class="aui-list-item-right"></div>
</div>
</li>
- <!--<li class="aui-list-item" onclick="app.loginByTouchId()">
+ <li class="aui-list-item" onclick="app.loginByTouchId()">
<div class="aui-list-item-label-icon">
- <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+ <i class="aui-iconfont aui-icon-gear aui-text-info"></i>
</div>
<div class="aui-list-item-inner ">
<div class="aui-list-item-title">指纹\人脸登录</div>
- <div class="aui-list-item-right"><input type="checkbox" id="login" class="aui-switch" ></div>
+ <div class="aui-list-item-right"><input type="checkbox" id="login" class="aui-switch" disabled ></div>
</div>
- </li>-->
+ </li>
+ </ul>
+ </section>
+ <section class="aui-content aui-margin-b-15 aui-margin-t-10">
+ <ul class="aui-list aui-list-in aui-margin-t-10 ">
<li class="aui-list-item" onclick="app.toPayPwd()">
<div class="aui-list-item-label-icon">
<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
</div>
</li>
</ul>
- <div style="padding: 20px;margin-top: 40px;">
- <a href="javascript:app.logout();" class="weui-btn weui-btn_warn">退出登录</a>
- </div>
</section>
</body>
<link rel="stylesheet" type="text/css" href="css/aui.css">
<link rel="stylesheet" type="text/css" href="css/weui.min.css">
<link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
- <title>签约代扣免密支付协议</title>
+ <title>市民卡免密代扣签约协议</title>
</head>
<body>
<header class="aui-bar aui-bar-nav" style="padding-top:25px;">
- <a class="aui-pull-left" href="main.html">
+ <a class="aui-pull-left" href="javascript:window.history.back()">
<span class="aui-iconfont aui-icon-left"></span>
</a>
- <div class="aui-title">签约代扣免密支付协议</div>
+ <div class="aui-title">市民卡免密代扣签约协议</div>
</header>
- <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:135px;left: 0;right: 0" id="content">
+ <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:10px;left: 0;right: 0" id="content">
</div>
- <div class="weui-footer weui-footer_fixed-bottom" style="background: #fff;display: none;" id="btn">
- <div style="margin-top: 10px;">
- <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
- <input id="agree" type="checkbox" class="weui-agree__checkbox" value="yes">
- <span class="weui-agree__text">
- 我已阅读并同意该协议
- </span>
- </label>
- </div>
- <section class="aui-content-padded" style="margin-top: 20px;">
- <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.agreeXY()">签约代扣协议</div>
- </section>
- </div>
+
</body>
</html>
--- /dev/null
+package de.niklasmerz.cordova.biometric;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AppCompatActivity;
+
+import com.exxbrain.android.biometric.BiometricPrompt;
+
+import java.util.concurrent.Executor;
+
+public class BiometricActivity extends AppCompatActivity {
+
+ private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 2;
+ private PromptInfo mPromptInfo;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setTitle(null);
+ int layout = getResources()
+ .getIdentifier("biometric_activity", "layout", getPackageName());
+ setContentView(layout);
+
+ if (savedInstanceState != null) {
+ return;
+ }
+
+ mPromptInfo = new PromptInfo.Builder(getIntent().getExtras()).build();
+ authenticate();
+
+ }
+
+ private void authenticate() {
+ final Handler handler = new Handler(Looper.getMainLooper());
+ Executor executor = handler::post;
+
+ BiometricPrompt biometricPrompt =
+ new BiometricPrompt(this, executor, mAuthenticationCallback);
+
+ BiometricPrompt.PromptInfo.Builder promptInfoBuilder = new BiometricPrompt.PromptInfo.Builder()
+ .setTitle(mPromptInfo.getTitle())
+ .setSubtitle(mPromptInfo.getSubtitle())
+ .setDescription(mPromptInfo.getDescription());
+
+ if (mPromptInfo.isDeviceCredentialAllowed()
+ && Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ promptInfoBuilder.setDeviceCredentialAllowed(true);
+ } else {
+ promptInfoBuilder.setNegativeButtonText(mPromptInfo.getCancelButtonTitle());
+ }
+
+ biometricPrompt.authenticate(promptInfoBuilder.build());
+ }
+
+ private BiometricPrompt.AuthenticationCallback mAuthenticationCallback =
+ new BiometricPrompt.AuthenticationCallback() {
+
+ @Override
+ public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
+ super.onAuthenticationError(errorCode, errString);
+ onError(errorCode, errString);
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
+ super.onAuthenticationSucceeded(result);
+ finishWithSuccess();
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+ super.onAuthenticationFailed();
+ }
+ };
+
+
+ // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ private void showAuthenticationScreen() {
+ KeyguardManager keyguardManager = ContextCompat
+ .getSystemService(this, KeyguardManager.class);
+ if (keyguardManager == null
+ || android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
+ return;
+ }
+ if (keyguardManager.isKeyguardSecure()) {
+ Intent intent = keyguardManager
+ .createConfirmDeviceCredentialIntent(mPromptInfo.getTitle(), mPromptInfo.getDescription());
+ this.startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
+ } else {
+ // Show a message that the user hasn't set up a lock screen.
+ finishWithError(PluginError.BIOMETRIC_SCREEN_GUARD_UNSECURED);
+ }
+ }
+
+ // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
+ if (resultCode == Activity.RESULT_OK) {
+ finishWithSuccess();
+ } else {
+ finishWithError(PluginError.BIOMETRIC_PIN_OR_PATTERN_DISMISSED);
+ }
+ }
+ }
+
+ private void onError(int errorCode, @NonNull CharSequence errString) {
+
+ switch (errorCode)
+ {
+ case BiometricPrompt.ERROR_USER_CANCELED:
+ case BiometricPrompt.ERROR_CANCELED:
+ finishWithError(PluginError.BIOMETRIC_DISMISSED);
+ return;
+ case BiometricPrompt.ERROR_NEGATIVE_BUTTON:
+ // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P && mPromptInfo.isDeviceCredentialAllowed()) {
+ showAuthenticationScreen();
+ return;
+ }
+ finishWithError(PluginError.BIOMETRIC_DISMISSED);
+ break;
+ case BiometricPrompt.ERROR_LOCKOUT:
+ finishWithError(PluginError.BIOMETRIC_LOCKED_OUT.getValue(), errString.toString());
+ break;
+ case BiometricPrompt.ERROR_LOCKOUT_PERMANENT:
+ finishWithError(PluginError.BIOMETRIC_LOCKED_OUT_PERMANENT.getValue(), errString.toString());
+ break;
+ default:
+ finishWithError(errorCode, errString.toString());
+ }
+ }
+
+ private void finishWithSuccess() {
+ setResult(RESULT_OK);
+ finish();
+ }
+
+ private void finishWithError(PluginError error) {
+ finishWithError(error.getValue(), error.getMessage());
+ }
+
+ private void finishWithError(int code, String message) {
+ Intent data = new Intent();
+ data.putExtra("code", code);
+ data.putExtra("message", message);
+ setResult(RESULT_CANCELED, data);
+ finish();
+ }
+}
--- /dev/null
+package de.niklasmerz.cordova.biometric;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.exxbrain.android.biometric.BiometricManager;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class Fingerprint extends CordovaPlugin {
+
+ private static final String TAG = "Fingerprint";
+ private CallbackContext mCallbackContext = null;
+
+ private static final int REQUEST_CODE_BIOMETRIC = 1;
+ private PromptInfo.Builder mPromptInfoBuilder;
+
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+ super.initialize(cordova, webView);
+ Log.v(TAG, "Init Fingerprint");
+ mPromptInfoBuilder = new PromptInfo.Builder(cordova.getActivity());
+ }
+
+ public boolean execute(final String action, JSONArray args, CallbackContext callbackContext) {
+
+ this.mCallbackContext = callbackContext;
+ Log.v(TAG, "Fingerprint action: " + action);
+
+ if (action.equals("authenticate")) {
+ executeAuthenticate(args);
+ return true;
+
+ } else if (action.equals("isAvailable")){
+ executeIsAvailable();
+ return true;
+ }
+
+ return false;
+ }
+
+ private void executeIsAvailable() {
+ PluginError error = canAuthenticate();
+ if (error != null) {
+ sendError(error);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
+ sendSuccess("biometric");
+ } else {
+ sendSuccess("finger");
+ }
+ }
+
+ private void executeAuthenticate(JSONArray args) {
+ PluginError error = canAuthenticate();
+ if (error != null) {
+ sendError(error);
+ return;
+ }
+ cordova.getActivity().runOnUiThread(() -> {
+ mPromptInfoBuilder.parseArgs(args);
+ Intent intent = new Intent(cordova.getActivity().getApplicationContext(), BiometricActivity.class);
+ intent.putExtras(mPromptInfoBuilder.build().getBundle());
+ this.cordova.startActivityForResult(this, intent, REQUEST_CODE_BIOMETRIC);
+ });
+ PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
+ pluginResult.setKeepCallback(true);
+ this.mCallbackContext.sendPluginResult(pluginResult);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ super.onActivityResult(requestCode, resultCode, intent);
+ if (requestCode != REQUEST_CODE_BIOMETRIC) {
+ return;
+ }
+ if (resultCode == Activity.RESULT_OK) {
+ sendSuccess("biometric_success");
+ } else if (intent != null) {
+ Bundle extras = intent.getExtras();
+ sendError(extras.getInt("code"), extras.getString("message"));
+ } else {
+ sendError(PluginError.BIOMETRIC_DISMISSED);
+ }
+ }
+
+ private PluginError canAuthenticate() {
+ int error = BiometricManager.from(cordova.getContext()).canAuthenticate();
+ switch (error) {
+ case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
+ case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
+ return PluginError.BIOMETRIC_HARDWARE_NOT_SUPPORTED;
+ case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
+ return PluginError.BIOMETRIC_NOT_ENROLLED;
+ default:
+ return null;
+ }
+ }
+
+ private void sendError(int code, String message) {
+ JSONObject resultJson = new JSONObject();
+ try {
+ resultJson.put("code", code);
+ resultJson.put("message", message);
+
+ PluginResult result = new PluginResult(PluginResult.Status.ERROR, resultJson);
+ result.setKeepCallback(true);
+ cordova.getActivity().runOnUiThread(() ->
+ Fingerprint.this.mCallbackContext.sendPluginResult(result));
+ } catch (JSONException e) {
+ Log.e(TAG, e.getMessage(), e);
+ }
+ }
+
+ private void sendError(PluginError error) {
+ sendError(error.getValue(), error.getMessage());
+ }
+
+ private void sendSuccess(String message) {
+ Log.e(TAG, message);
+ cordova.getActivity().runOnUiThread(() ->
+ this.mCallbackContext.success(message));
+ }
+}
--- /dev/null
+package de.niklasmerz.cordova.biometric;
+
+public enum PluginError {
+
+ BIOMETRIC_AUTHENTICATION_FAILED(-102, "Authentication failed"),
+ BIOMETRIC_HARDWARE_NOT_SUPPORTED(-104),
+ BIOMETRIC_NOT_ENROLLED(-106),
+ BIOMETRIC_DISMISSED(-108),
+ BIOMETRIC_PIN_OR_PATTERN_DISMISSED(-109),
+ BIOMETRIC_SCREEN_GUARD_UNSECURED(-110,
+ "Go to 'Settings -> Security -> Screenlock' to set up a lock screen"),
+ BIOMETRIC_LOCKED_OUT(-111),
+ BIOMETRIC_LOCKED_OUT_PERMANENT(-112);
+
+ private int value;
+ private String message;
+
+ PluginError(int value) {
+ this.value = value;
+ this.message = this.name();
+ }
+
+ PluginError(int value, String message) {
+ this.value = value;
+ this.message = message;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
--- /dev/null
+package de.niklasmerz.cordova.biometric;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+class PromptInfo {
+
+ private static final String DISABLE_BACKUP = "disableBackup";
+ private static final String TITLE = "title";
+ private static final String SUBTITLE = "subtitle";
+ private static final String DESCRIPTION = "description";
+ private static final String FALLBACK_BUTTON_TITLE = "fallbackButtonTitle";
+ private static final String CANCEL_BUTTON_TITLE = "cancelButtonTitle";
+
+ private Bundle bundle = new Bundle();
+
+ Bundle getBundle() {
+ return bundle;
+ }
+
+ String getTitle() {
+ return bundle.getString(TITLE);
+ }
+
+ String getSubtitle() {
+ return bundle.getString(SUBTITLE);
+ }
+
+ String getDescription() {
+ return bundle.getString(DESCRIPTION);
+ }
+
+ boolean isDeviceCredentialAllowed() {
+ return !bundle.getBoolean(DISABLE_BACKUP);
+ }
+
+ String getFallbackButtonTitle() {
+ return bundle.getString(FALLBACK_BUTTON_TITLE);
+ }
+
+ String getCancelButtonTitle() {
+ return bundle.getString(CANCEL_BUTTON_TITLE);
+ }
+
+ public static final class Builder {
+ private static final String TAG = "PromptInfo.Builder";
+ private Bundle bundle;
+ private boolean disableBackup = false;
+ private String title;
+ private String subtitle = null;
+ private String description = null;
+ private String fallbackButtonTitle = "Use backup";
+ private String cancelButtonTitle = "Cancel";
+
+ Builder(Context context) {
+ PackageManager packageManager = context.getPackageManager();
+ try {
+ ApplicationInfo app = packageManager
+ .getApplicationInfo(context.getPackageName(), 0);
+ title = packageManager.getApplicationLabel(app) + " Biometric Sign On";
+ } catch (PackageManager.NameNotFoundException e) {
+ title = "Biometric Sign On";
+ }
+ }
+
+ Builder(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ public PromptInfo build() {
+ PromptInfo promptInfo = new PromptInfo();
+
+ if (this.bundle != null) {
+ promptInfo.bundle = bundle;
+ return promptInfo;
+ }
+
+ Bundle bundle = new Bundle();
+ bundle.putString(SUBTITLE, this.subtitle);
+ bundle.putString(TITLE, this.title);
+ bundle.putString(DESCRIPTION, this.description);
+ bundle.putString(FALLBACK_BUTTON_TITLE, this.fallbackButtonTitle);
+ bundle.putString(CANCEL_BUTTON_TITLE, this.cancelButtonTitle);
+ bundle.putBoolean(DISABLE_BACKUP, this.disableBackup);
+ promptInfo.bundle = bundle;
+
+ return promptInfo;
+ }
+
+ void parseArgs(JSONArray args) {
+ JSONObject argsObject;
+ try {
+ argsObject = args.getJSONObject(0);
+ } catch (JSONException e) {
+ Log.e(TAG, "Can't parse args. Defaults will be used.", e);
+ return;
+ }
+ disableBackup = getBooleanArg(argsObject, DISABLE_BACKUP, disableBackup);
+ title = getStringArg(argsObject, TITLE, title);
+ subtitle = getStringArg(argsObject, SUBTITLE, subtitle);
+ description = getStringArg(argsObject, DESCRIPTION, description);
+ fallbackButtonTitle = getStringArg(argsObject, FALLBACK_BUTTON_TITLE, "Use Backup");
+ cancelButtonTitle = getStringArg(argsObject, CANCEL_BUTTON_TITLE, "Cancel");
+ }
+
+ private Boolean getBooleanArg(JSONObject argsObject, String name, Boolean defaultValue) {
+ if (argsObject.has(name)){
+ try {
+ return argsObject.getBoolean(name);
+ } catch (JSONException e) {
+ Log.e(TAG, "Can't parse '" + name + "'. Default will be used.", e);
+ }
+ }
+ return defaultValue;
+ }
+
+ private String getStringArg(JSONObject argsObject, String name, String defaultValue) {
+ if (argsObject.optString(name) != null
+ && !argsObject.optString(name).isEmpty()){
+ try {
+ return argsObject.getString(name);
+ } catch (JSONException e) {
+ Log.e(TAG, "Can't parse '" + name + "'. Default will be used.", e);
+ }
+ }
+ return defaultValue;
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (C) https://github.com/mjwheatley/cordova-plugin-android-fingerprint-auth
- * Modifications copyright (C) 2016 Niklas Merz
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package de.niklasmerz.cordova.fingerprint;
-
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaInterface;
-
-import android.annotation.TargetApi;
-import android.app.FragmentTransaction;
-import android.app.KeyguardManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.hardware.fingerprint.FingerprintManager;
-import android.os.Bundle;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyPermanentlyInvalidatedException;
-import android.security.keystore.KeyProperties;
-import android.util.Base64;
-import android.util.DisplayMetrics;
-import android.util.Log;
-
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.IOException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.util.Locale;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.KeyGenerator;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
-
-@TargetApi(23)
-public class Fingerprint extends CordovaPlugin {
-
- public static final String TAG = "Fingerprint";
- public static String packageName;
-
- private static final String DIALOG_FRAGMENT_TAG = "FpAuthDialog";
- private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
-
- KeyguardManager mKeyguardManager;
- FingerprintAuthenticationDialogFragment mFragment;
- public static KeyStore mKeyStore;
- public static KeyGenerator mKeyGenerator;
- public static Cipher mCipher;
- private FingerprintManager mFingerPrintManager;
-
- public static CallbackContext mCallbackContext;
- public static PluginResult mPluginResult;
-
- /**
- * Alias for our key in the Android Key Store
- */
- private static String mClientId;
- /**
- * Used to encrypt token
- */
- private static String mClientSecret;
-
- /**
- * Options
- */
- private static boolean mDisableBackup = false;
-
- /**
- * Constructor.
- */
- public Fingerprint() {
- }
-
- /**
- * Sets the context of the Command. This can then be used to do things like
- * get file paths associated with the Activity.
- *
- * @param cordova The context of the main Activity.
- * @param webView The CordovaWebView Cordova is running in.
- */
-
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
- Log.v(TAG, "Init Fingerprint");
- packageName = cordova.getActivity().getApplicationContext().getPackageName();
- mPluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
-
- if (android.os.Build.VERSION.SDK_INT < 23) {
- return;
- }
-
- mKeyguardManager = cordova.getActivity().getSystemService(KeyguardManager.class);
- mFingerPrintManager = cordova.getActivity().getApplicationContext()
- .getSystemService(FingerprintManager.class);
-
- try {
- mKeyGenerator = KeyGenerator.getInstance(
- KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
- mKeyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
-
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
- } catch (NoSuchProviderException e) {
- throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
- } catch (KeyStoreException e) {
- throw new RuntimeException("Failed to get an instance of KeyStore", e);
- }
-
- try {
- mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
- + KeyProperties.BLOCK_MODE_CBC + "/"
- + KeyProperties.ENCRYPTION_PADDING_PKCS7);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("Failed to get an instance of Cipher", e);
- } catch (NoSuchPaddingException e) {
- throw new RuntimeException("Failed to get an instance of Cipher", e);
- }
- }
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackContext The callback id used when calling back into JavaScript.
- * @return A PluginResult object with a status and message.
- */
- public boolean execute(final String action,
- JSONArray args,
- CallbackContext callbackContext) throws JSONException {
- mCallbackContext = callbackContext;
- Log.v(TAG, "Fingerprint action: " + action);
- if (android.os.Build.VERSION.SDK_INT < 23) {
- Log.e(TAG, "minimum SDK version 23 required");
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.error("minimum SDK version 23 required");
- mCallbackContext.sendPluginResult(mPluginResult);
- return true;
- }
-
- final JSONObject arg_object = args.getJSONObject(0);
-
- if (action.equals("authenticate")) {
- if (!arg_object.has("clientId") || !arg_object.has("clientSecret")) {
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.error("Missing required parameters");
- mCallbackContext.sendPluginResult(mPluginResult);
- return true;
- }
- mClientId = arg_object.getString("clientId");
- mClientSecret = arg_object.getString("clientSecret");
- if (arg_object.has("disableBackup")) {
- mDisableBackup = arg_object.getBoolean("disableBackup");
- }
- // Set language
- Resources res = cordova.getActivity().getResources();
- // Change locale settings in the app.
- DisplayMetrics dm = res.getDisplayMetrics();
- Configuration conf = res.getConfiguration();
- //Do not change locale
- res.updateConfiguration(conf, dm);
-
- if (isFingerprintAuthAvailable()) {
- SecretKey key = getSecretKey();
- boolean isCipherInit = true;
- if (key == null) {
- if (createKey()) {
- key = getSecretKey();
- }
- }
- if (key != null && !initCipher()) {
- isCipherInit = false;
- }
- if (key != null) {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- // Set up the crypto object for later. The object will be authenticated by use
- // of the fingerprint.
- mFragment = new FingerprintAuthenticationDialogFragment();
- Bundle bundle = new Bundle();
- bundle.putBoolean("disableBackup", mDisableBackup);
- mFragment.setArguments(bundle);
-
- if (initCipher()) {
- mFragment.setCancelable(false);
- // Show the fingerprint dialog. The user has the option to use the fingerprint with
- // crypto, or you can fall back to using a server-side verified password.
- mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
- FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction();
- transaction.add(mFragment, DIALOG_FRAGMENT_TAG);
- transaction.commitAllowingStateLoss();
- } else {
- if (!mDisableBackup) {
- // This happens if the lock screen has been disabled or or a fingerprint got
- // enrolled. Thus show the dialog to authenticate with their password
- mFragment.setCryptoObject(new FingerprintManager
- .CryptoObject(mCipher));
- mFragment.setStage(FingerprintAuthenticationDialogFragment
- .Stage.NEW_FINGERPRINT_ENROLLED);
- FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction();
- transaction.add(mFragment, DIALOG_FRAGMENT_TAG);
- transaction.commitAllowingStateLoss();
- } else {
- mCallbackContext.error("Failed to init Cipher and backup disabled.");
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.sendPluginResult(mPluginResult);
- }
- }
- }
- });
- mPluginResult.setKeepCallback(true);
- } else {
- mCallbackContext.sendPluginResult(mPluginResult);
- }
-
- } else {
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.error("Fingerprint authentication not available");
- mCallbackContext.sendPluginResult(mPluginResult);
- }
- return true;
- } else if (action.equals("isAvailable")) {
- if(isFingerprintAuthAvailable() && mFingerPrintManager.isHardwareDetected() && mFingerPrintManager.hasEnrolledFingerprints()){
- mPluginResult = new PluginResult(PluginResult.Status.OK, "finger");
- mCallbackContext.success("finger");
- }else{
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
-
- if (mFingerPrintManager.isHardwareDetected() && !mFingerPrintManager.hasEnrolledFingerprints()) {
- mCallbackContext.error("Fingerprint authentication not ready");
- } else {
- mCallbackContext.error("Fingerprint authentication not available");
- }
- }
- mCallbackContext.sendPluginResult(mPluginResult);
- return true;
- }
- return false;
- }
-
- private boolean isFingerprintAuthAvailable() {
- return mFingerPrintManager.isHardwareDetected()
- && mFingerPrintManager.hasEnrolledFingerprints();
- }
-
- /**
- * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()}
- * method.
- *
- * @return {@code true} if initialization is successful, {@code false} if the lock screen has
- * been disabled or reset after the key was generated, or if a fingerprint got enrolled after
- * the key was generated.
- */
- private static boolean initCipher() {
- boolean initCipher = false;
- String errorMessage = "";
- String initCipherExceptionErrorPrefix = "Failed to init Cipher: ";
- try {
- SecretKey key = getSecretKey();
- mCipher.init(Cipher.ENCRYPT_MODE, key);
- initCipher = true;
- } catch (InvalidKeyException e) {
- errorMessage = initCipherExceptionErrorPrefix + "InvalidKeyException: " + e.toString();
-
- }
- if (!initCipher) {
- Log.e(TAG, errorMessage);
- createKey();
- }
- return initCipher;
- }
-
- private static SecretKey getSecretKey() {
- String errorMessage = "";
- String getSecretKeyExceptionErrorPrefix = "Failed to get SecretKey from KeyStore: ";
- SecretKey key = null;
- try {
- mKeyStore.load(null);
- key = (SecretKey) mKeyStore.getKey(mClientId, null);
- } catch (KeyStoreException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "KeyStoreException: " + e.toString();;
- } catch (CertificateException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "CertificateException: " + e.toString();;
- } catch (UnrecoverableKeyException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "UnrecoverableKeyException: " + e.toString();;
- } catch (IOException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "IOException: " + e.toString();;
- } catch (NoSuchAlgorithmException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "NoSuchAlgorithmException: " + e.toString();;
- }
- if (key == null) {
- Log.e(TAG, errorMessage);
- }
- return key;
- }
-
- /**
- * Creates a symmetric key in the Android Key Store which can only be used after the user has
- * authenticated with fingerprint.
- */
- public static boolean createKey() {
- String errorMessage = "";
- String createKeyExceptionErrorPrefix = "Failed to create key: ";
- boolean isKeyCreated = false;
- // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
- // for your flow. Use of keys is necessary if you need to know if the set of
- // enrolled fingerprints has changed.
- try {
- mKeyStore.load(null);
- // Set the alias of the entry in Android KeyStore where the key will appear
- // and the constrains (purposes) in the constructor of the Builder
- mKeyGenerator.init(new KeyGenParameterSpec.Builder(mClientId,
- KeyProperties.PURPOSE_ENCRYPT |
- KeyProperties.PURPOSE_DECRYPT)
- .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
- // Require the user to authenticate with a fingerprint to authorize every use
- // of the key
- .setUserAuthenticationRequired(true)
- .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
- .build());
- mKeyGenerator.generateKey();
- isKeyCreated = true;
- } catch (NoSuchAlgorithmException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "NoSuchAlgorithmException: " + e.toString();;
- } catch (InvalidAlgorithmParameterException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "InvalidAlgorithmParameterException: " + e.toString();;
- } catch (CertificateException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "CertificateException: " + e.toString();;
- } catch (IOException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "IOException: " + e.toString();;
- }
- if (!isKeyCreated) {
- Log.e(TAG, errorMessage);
- setPluginResultError(errorMessage);
- }
- return isKeyCreated;
- }
-
- public static void onAuthenticated(boolean withFingerprint) {
- JSONObject resultJson = new JSONObject();
- String errorMessage = "";
- boolean createdResultJson = false;
- try {
-
- if (withFingerprint) {
- // If the user has authenticated with fingerprint, verify that using cryptography and
- // then return the encrypted token
- byte[] encrypted = tryEncrypt();
- resultJson.put("withFingerprint", Base64.encodeToString(encrypted, 0 /* flags */));
- } else {
- // Authentication happened with backup password.
- resultJson.put("withPassword", true);
-
- // if failed to init cipher because of InvalidKeyException, create new key
- if (!initCipher()) {
- createKey();
- }
- }
- createdResultJson = true;
- } catch (BadPaddingException e) {
- errorMessage = "Failed to encrypt the data with the generated key:" +
- " BadPaddingException: " + e.getMessage();
- Log.e(TAG, errorMessage);
- } catch (IllegalBlockSizeException e) {
- errorMessage = "Failed to encrypt the data with the generated key: " +
- "IllegalBlockSizeException: " + e.getMessage();
- Log.e(TAG, errorMessage);
- } catch (JSONException e) {
- errorMessage = "Failed to set resultJson key value pair: " + e.getMessage();
- Log.e(TAG, errorMessage);
- }
-
- if (createdResultJson) {
- mCallbackContext.success(resultJson);
- mPluginResult = new PluginResult(PluginResult.Status.OK);
- } else {
- mCallbackContext.error(errorMessage);
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- }
- mCallbackContext.sendPluginResult(mPluginResult);
- }
-
- public static void onCancelled() {
- mCallbackContext.error("Cancelled");
- }
-
- /**
- * Tries to encrypt some data with the generated key in {@link #createKey} which is
- * only works if the user has just authenticated via fingerprint.
- */
- private static byte[] tryEncrypt() throws BadPaddingException, IllegalBlockSizeException {
- return mCipher.doFinal(mClientSecret.getBytes());
- }
-
- public static boolean setPluginResultError(String errorMessage) {
- mCallbackContext.error(errorMessage);
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- return false;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * Modifications copyright (C) 2016 Niklas Merz
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package de.niklasmerz.cordova.fingerprint;
-
-import android.app.DialogFragment;
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.hardware.fingerprint.FingerprintManager;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-/**
- * A dialog which uses fingerprint APIs to authenticate the user, and falls back to password
- * authentication if fingerprint is not available.
- */
-public class FingerprintAuthenticationDialogFragment extends DialogFragment
- implements FingerprintUiHelper.Callback {
-
- private static final String TAG = "FingerprintAuthDialog";
- private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
-
- private Button mCancelButton;
- private Button mSecondDialogButton;
- private View mFingerprintContent;
-
- private Stage mStage = Stage.FINGERPRINT;
-
- private KeyguardManager mKeyguardManager;
- private FingerprintManager.CryptoObject mCryptoObject;
- private FingerprintUiHelper mFingerprintUiHelper;
- FingerprintUiHelper.FingerprintUiHelperBuilder mFingerprintUiHelperBuilder;
-
- boolean disableBackup;
-
- public FingerprintAuthenticationDialogFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Do not create a new Fragment when the Activity is re-created such as orientation changes.
- setRetainInstance(true);
- setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
-
- mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
- mFingerprintUiHelperBuilder = new FingerprintUiHelper.FingerprintUiHelperBuilder(
- getContext(), getContext().getSystemService(FingerprintManager.class));
-
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- Bundle args = getArguments();
- disableBackup = args.getBoolean("disableBackup");
- Log.d(TAG, "disableBackup: " + disableBackup);
-
- int fingerprint_auth_dialog_title_id = getResources()
- .getIdentifier("fingerprint_auth_dialog_title", "string",
- Fingerprint.packageName);
- getDialog().setTitle(getString(fingerprint_auth_dialog_title_id));
- int fingerprint_dialog_container_id = getResources()
- .getIdentifier("fingerprint_dialog_container", "layout",
- Fingerprint.packageName);
- View v = inflater.inflate(fingerprint_dialog_container_id, container, false);
- int cancel_button_id = getResources()
- .getIdentifier("cancel_button", "id", Fingerprint.packageName);
- mCancelButton = (Button) v.findViewById(cancel_button_id);
- mCancelButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Fingerprint.onCancelled();
- dismissAllowingStateLoss();
- }
- });
-
- int second_dialog_button_id = getResources()
- .getIdentifier("second_dialog_button", "id", Fingerprint.packageName);
- mSecondDialogButton = (Button) v.findViewById(second_dialog_button_id);
- if (disableBackup) {
- mSecondDialogButton.setVisibility(View.GONE);
- }
- mSecondDialogButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- goToBackup();
- }
- });
- int fingerprint_container_id = getResources()
- .getIdentifier("fingerprint_container", "id", Fingerprint.packageName);
- mFingerprintContent = v.findViewById(fingerprint_container_id);
-
- int new_fingerprint_enrolled_description_id = getResources()
- .getIdentifier("new_fingerprint_enrolled_description", "id",
- Fingerprint.packageName);
-
- int fingerprint_icon_id = getResources()
- .getIdentifier("fingerprint_icon", "id", Fingerprint.packageName);
- int fingerprint_status_id = getResources()
- .getIdentifier("fingerprint_status", "id", Fingerprint.packageName);
- mFingerprintUiHelper = mFingerprintUiHelperBuilder.build(
- (ImageView) v.findViewById(fingerprint_icon_id),
- (TextView) v.findViewById(fingerprint_status_id), this);
- updateStage();
-
- // If fingerprint authentication is not available, switch immediately to the backup
- // (password) screen.
- if (!mFingerprintUiHelper.isFingerprintAuthAvailable()) {
- goToBackup();
- }
- return v;
- }
-
-
- @Override
- public void onResume() {
- super.onResume();
- if (mStage == Stage.FINGERPRINT) {
- mFingerprintUiHelper.startListening(mCryptoObject);
- }
- }
-
- public void setStage(Stage stage) {
- mStage = stage;
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mFingerprintUiHelper.stopListening();
- }
-
- /**
- * Sets the crypto object to be passed in when authenticating with fingerprint.
- */
- public void setCryptoObject(FingerprintManager.CryptoObject cryptoObject) {
- mCryptoObject = cryptoObject;
- }
-
- /**
- * Switches to backup (password) screen. This either can happen when fingerprint is not
- * available or the user chooses to use the password authentication method by pressing the
- * button. This can also happen when the user had too many fingerprint attempts.
- */
- private void goToBackup() {
- if(disableBackup)
- {
- Fingerprint.onCancelled();
- dismissAllowingStateLoss();
- }
- else{
- mStage = Stage.BACKUP;
- updateStage();
- }
- }
-
- private void updateStage() {
- int cancel_id = getResources()
- .getIdentifier("fingerprint_cancel", "string", Fingerprint.packageName);
- switch (mStage) {
- case FINGERPRINT:
- mCancelButton.setText(cancel_id);
- int use_backup_id = getResources()
- .getIdentifier("fingerprint_use_backup", "string", Fingerprint.packageName);
- mSecondDialogButton.setText(use_backup_id);
- mFingerprintContent.setVisibility(View.VISIBLE);
- break;
- case NEW_FINGERPRINT_ENROLLED:
- // Intentional fall through
- case BACKUP:
- if (mStage == Stage.NEW_FINGERPRINT_ENROLLED) {
-
- }
- if (!mKeyguardManager.isKeyguardSecure()) {
- // Show a message that the user hasn't set up a lock screen.
- int secure_lock_screen_required_id = getResources()
- .getIdentifier("secure_lock_screen_required", "string",
- Fingerprint.packageName);
- Toast.makeText(getContext(),
- getString(secure_lock_screen_required_id),
- Toast.LENGTH_LONG).show();
- return;
- }
- showAuthenticationScreen();
- break;
- }
- }
-
- private void showAuthenticationScreen() {
- // Create the Confirm Credentials screen. You can customize the title and description. Or
- // we will provide a generic one for you if you leave it null
- Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
- if (intent != null) {
- startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
- // Challenge completed, proceed with using cipher
- if (resultCode == getActivity().RESULT_OK) {
- Fingerprint.onAuthenticated(false /* used backup */);
- } else {
- // The user canceled or didn’t complete the lock screen
- // operation. Go to error/cancellation flow.
- Fingerprint.onCancelled();
- }
- dismissAllowingStateLoss();
- }
- }
-
- @Override
- public void onAuthenticated() {
- // Callback from FingerprintUiHelper. Let the activity know that authentication was
- // successful.
- Fingerprint.onAuthenticated(true /* withFingerprint */);
- dismissAllowingStateLoss();
- }
-
- @Override
- public void onError() {
- if(this.getActivity() != null)
- goToBackup();
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- Fingerprint.onCancelled();
- }
-
- /**
- * Enumeration to indicate which authentication method the user is trying to authenticate with.
- */
- public enum Stage {
- FINGERPRINT,
- NEW_FINGERPRINT_ENROLLED,
- BACKUP
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * Modifications copyright (C) 2016 Niklas Merz
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package de.niklasmerz.cordova.fingerprint;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.hardware.fingerprint.FingerprintManager;
-import android.os.CancellationSignal;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-
-/**
- * Small helper class to manage text/icon around fingerprint authentication UI.
- */
-@TargetApi(23)
-public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
-
- static final long ERROR_TIMEOUT_MILLIS = 1600;
- static final long SUCCESS_DELAY_MILLIS = 1300;
-
- private final Context mContext;
- private final FingerprintManager mFingerprintManager;
- private final ImageView mIcon;
- private final TextView mErrorTextView;
- private final Callback mCallback;
- private CancellationSignal mCancellationSignal;
-
- boolean mSelfCancelled;
-
- /**
- * Builder class for {@link FingerprintUiHelper} in which injected fields from Dagger
- * holds its fields and takes other arguments in the {@link #build} method.
- */
- public static class FingerprintUiHelperBuilder {
- private final FingerprintManager mFingerPrintManager;
- private final Context mContext;
-
- public FingerprintUiHelperBuilder(Context context, FingerprintManager fingerprintManager) {
- mFingerPrintManager = fingerprintManager;
- mContext = context;
- }
-
- public FingerprintUiHelper build(ImageView icon, TextView errorTextView, Callback callback) {
- return new FingerprintUiHelper(mContext, mFingerPrintManager, icon, errorTextView,
- callback);
- }
- }
-
- /**
- * Constructor for {@link FingerprintUiHelper}. This method is expected to be called from
- * only the {@link FingerprintUiHelperBuilder} class.
- */
- private FingerprintUiHelper(Context context, FingerprintManager fingerprintManager,
- ImageView icon, TextView errorTextView, Callback callback) {
- mFingerprintManager = fingerprintManager;
- mIcon = icon;
- mErrorTextView = errorTextView;
- mCallback = callback;
- mContext = context;
- }
-
- public boolean isFingerprintAuthAvailable() {
- return mFingerprintManager.isHardwareDetected()
- && mFingerprintManager.hasEnrolledFingerprints();
- }
-
- public void startListening(FingerprintManager.CryptoObject cryptoObject) {
- if (!isFingerprintAuthAvailable()) {
- return;
- }
- mCancellationSignal = new CancellationSignal();
- mSelfCancelled = false;
- mFingerprintManager
- .authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
-
- int ic_fp_40px_id = mContext.getResources()
- .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fp_40px_id);
- }
-
- public void stopListening() {
- if (mCancellationSignal != null) {
- mSelfCancelled = true;
- mCancellationSignal.cancel();
- mCancellationSignal = null;
- }
- }
-
- @Override
- public void onAuthenticationError(int errMsgId, CharSequence errString) {
- if (!mSelfCancelled) {
- showError(errString);
- mIcon.postDelayed(new Runnable() {
- @Override
- public void run() {
- mCallback.onError();
- }
- }, ERROR_TIMEOUT_MILLIS);
- }
- }
-
- @Override
- public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
- showError(helpString);
- }
-
- @Override
- public void onAuthenticationFailed() {
- int fingerprint_not_recognized_id = mContext.getResources()
- .getIdentifier("fingerprint_not_recognized", "string", Fingerprint.packageName);
- showError(mIcon.getResources().getString(
- fingerprint_not_recognized_id));
- }
-
- @Override
- public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
- mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
- int ic_fingerprint_success_id = mContext.getResources()
- .getIdentifier("ic_fingerprint_success", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fingerprint_success_id);
- int success_color_id = mContext.getResources()
- .getIdentifier("success_color", "color", Fingerprint.packageName);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(success_color_id, null));
- int fingerprint_success_id = mContext.getResources()
- .getIdentifier("fingerprint_success", "string", Fingerprint.packageName);
- mErrorTextView.setText(
- mErrorTextView.getResources().getString(fingerprint_success_id));
- mIcon.postDelayed(new Runnable() {
- @Override
- public void run() {
- mCallback.onAuthenticated();
- }
- }, SUCCESS_DELAY_MILLIS);
- }
-
- private void showError(CharSequence error) {
- int ic_fingerprint_error_id = mContext.getResources()
- .getIdentifier("ic_fingerprint_error", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fingerprint_error_id);
- mErrorTextView.setText(error);
- int warning_color_id = mContext.getResources()
- .getIdentifier("warning_color", "color", Fingerprint.packageName);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(warning_color_id, null));
- mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
- mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
- }
-
- Runnable mResetErrorTextRunnable = new Runnable() {
- @Override
- public void run() {
- int hint_color_id = mContext.getResources()
- .getIdentifier("hint_color", "color", Fingerprint.packageName);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(hint_color_id, null));
- int fingerprint_hint_id = mContext.getResources()
- .getIdentifier("fingerprint_hint", "string", Fingerprint.packageName);
- mErrorTextView.setText(
- mErrorTextView.getResources().getString(fingerprint_hint_id));
- int ic_fp_40px_id = mContext.getResources()
- .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fp_40px_id);
- }
- };
-
- public interface Callback {
-
- void onAuthenticated();
-
- void onError();
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="40.0dp"
- android:height="40.0dp"
- android:viewportWidth="40.0"
- android:viewportHeight="40.0">
- <path
- android:pathData="M20.0,0.0C8.96,0.0 0.0,8.95 0.0,20.0s8.96,20.0 20.0,20.0c11.04,0.0 20.0,-8.95 20.0,-20.0S31.04,0.0 20.0,0.0z"
- android:fillColor="#F4511E"/>
- <path
- android:pathData="M21.33,29.33l-2.67,0.0l0.0,-2.67l2.67,0.0L21.33,29.33zM21.33,22.67l-2.67,0.0l0.0,-12.0l2.67,0.0L21.33,22.67z"
- android:fillColor="#FFFFFF"/>
-</vector>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="40.0dp"
- android:height="40.0dp"
- android:viewportWidth="40.0"
- android:viewportHeight="40.0">
- <path
- android:pathData="M20.0,20.0m-20.0,0.0a20.0,20.0 0.0,1.0 1.0,40.0 0.0a20.0,20.0 0.0,1.0 1.0,-40.0 0.0"
- android:fillColor="#009688"/>
- <path
- android:pathData="M11.2,21.41l1.63,-1.619999 4.17,4.169998 10.59,-10.589999 1.619999,1.63 -12.209999,12.209999z"
- android:fillColor="#FFFFFF"/>
-</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent" android:layout_height="match_parent">
+
+</FrameLayout>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <include layout="@layout/fingerprint_dialog_content" />
-
- </FrameLayout>
-
- <LinearLayout
- android:id="@+id/buttonPanel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingStart="12dp"
- android:paddingEnd="12dp"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:gravity="bottom"
- style="?android:attr/buttonBarStyle">
-
- <Space
- android:id="@+id/spacer"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:visibility="invisible" />
- <Button
- android:id="@+id/cancel_button"
- style="?android:attr/buttonBarNegativeButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <Button
- android:id="@+id/second_dialog_button"
- style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/fingerprint_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="8dp"
- android:paddingStart="24dp"
- android:paddingEnd="24dp"
- android:paddingTop="16dp">
-
- <TextView
- android:id="@+id/fingerprint_description"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:text="@string/fingerprint_description"
- android:textAppearance="@android:style/TextAppearance.Material.Subhead"
- android:textColor="?android:attr/textColorSecondary"/>
-
-
- <ImageView
- android:id="@+id/fingerprint_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@+id/fingerprint_description"
- android:layout_marginTop="20dp"
- android:src="@drawable/ic_fp_40px" />
-
- <TextView
- android:id="@+id/fingerprint_status"
- style="@android:style/TextAppearance.Material.Body1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBottom="@+id/fingerprint_icon"
- android:layout_alignTop="@+id/fingerprint_icon"
- android:layout_marginStart="16dp"
- android:layout_toEndOf="@+id/fingerprint_icon"
- android:gravity="center_vertical"
- android:text="@string/fingerprint_hint"
- android:textColor="@color/hint_color" />
-</RelativeLayout>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Annuller</string>
- <string name="fingerprint_use_backup">Brug backup</string>
- <string name="fingerprint_auth_dialog_title">Fingeraftryk Login</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Bekræft fingeraftryk for at fortsætte</string>
- <string name="fingerprint_hint">Rør sensor</string>
- <string name="fingerprint_not_recognized">Fingeraftryk ikke genkendt. Prøv igen.</string>
- <string name="fingerprint_success">Fingeraftryk godkendt</string>
- <string name="new_fingerprint_enrolled_description">Et nyt fingeraftryk blev tilføjet til denne enhed så din adgangskode er krævet.</string>
- <string name="secure_lock_screen_required">Sikring af skærmlås krævet!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Abbrechen</string>
- <string name="fingerprint_use_backup">Passwort</string>
- <string name="fingerprint_auth_dialog_title">Authentifizierung</string>
- <string name="fingerprint_ok">OK</string>
- <string name="fingerprint_description">Fingerabdruck bestätigen</string>
- <string name="fingerprint_hint">Fingerabdrucksensor</string>
- <string name="fingerprint_not_recognized">Fingerabdruck nicht erkannt. Versuchen Sie es erneut</string>
- <string name="fingerprint_success">Authentifiziert</string>
- <string name="new_fingerprint_enrolled_description">Ein neuer Fingerabdruck wurde gespeichert. Bitte geben Sie ihr Passwort ein.</string>
- <string name="secure_lock_screen_required">Passwortgeschützter Sperrbildschirm benötigt</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Ακύρωση</string>
- <string name="fingerprint_use_backup">Χρήση αρχείου</string>
- <string name="fingerprint_auth_dialog_title">Ελεγχος αποτυπώματος</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Επιβεβαίωση αποτυπώματος</string>
- <string name="fingerprint_hint">Αιθηστήρας αφής</string>
- <string name="fingerprint_not_recognized">Σφάλμα. Προσπαθήστε ξανά</string>
- <string name="fingerprint_success">Σωστό αποτύπωμα</string>
- <string name="new_fingerprint_enrolled_description">Νεο αποτύπωμα προστέθηκε , απαιτείται ο κωδικός σας.</string>
- <string name="secure_lock_screen_required">Απαιτείται κλειδωμα οθόνης</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Cancelar</string>
- <string name="fingerprint_use_backup">El Respaldo</string>
- <string name="fingerprint_auth_dialog_title">Autenticación de Huellas Digitales</string>
- <string name="fingerprint_ok">De Acuerdo</string>
- <string name="fingerprint_description">Confirmar la huella digital para continuar</string>
- <string name="fingerprint_hint">Sensor tactil</string>
- <string name="fingerprint_not_recognized">No se reconoce la huella digital. Inténtalo de nuevo.</string>
- <string name="fingerprint_success">Reconocido de huella dactilar</string>
- <string name="new_fingerprint_enrolled_description">Una nueva huella digital fue agregada a este dispositivo, por lo que se requiere la contraseña.</string>
- <string name="secure_lock_screen_required">¡Requiere pantalla de bloqueo seguro!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Annuler</string>
- <string name="fingerprint_use_backup">Utiliser la sauvegarde</string>
- <string name="fingerprint_auth_dialog_title">Authentification par empreinte digitale</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Confirmer l\'empreinte pour continuer</string>
- <string name="fingerprint_hint">Toucher le capteur</string>
- <string name="fingerprint_not_recognized">Empreinte non reconnue. Essayer à nouveau.</string>
- <string name="fingerprint_success">Empreinte reconnue</string>
- <string name="new_fingerprint_enrolled_description">Une nouvelle empreinte digitale a été ajoutée à ce dispositif, de sorte que votre mot de passe est nécessaire.</string>
- <string name="secure_lock_screen_required">Écran de verrouillage sécurisé nécessaire!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Cancella</string>
- <string name="fingerprint_use_backup">Usa backup</string>
- <string name="fingerprint_auth_dialog_title">Autenticazione impronta digitale</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Conferma l\'impronta digitale per continuare</string>
- <string name="fingerprint_hint">Sensore Touch</string>
- <string name="fingerprint_not_recognized">Impronta digitale non riconosciuta. Riprova.</string>
- <string name="fingerprint_success">Impronta digitale riconosciuta</string>
- <string name="new_fingerprint_enrolled_description">Una nuova impronta è stata aggiunta a questo dispositivo, quindi è necessaria la tua password</string>
- <string name="secure_lock_screen_required">Blocco schermo richiesto!</string>
-</resources>
+++ /dev/null
-<resources>
- <string name="fingerprint_cancel">Annuleer</string>
- <string name="fingerprint_use_backup">Back-up gebruiken</string>
- <string name="fingerprint_auth_dialog_title">Authenticatie met vingerafdruk</string>
- <string name="fingerprint_ok">OK</string>
- <string name="fingerprint_description">Vingerafdruk bevestigen om verder te gaan</string>
- <string name="fingerprint_hint">Aanraaksensor</string>
- <string name="fingerprint_not_recognized">Vingerafdruk niet herkend.Opnieuw proberen.</string>
- <string name="fingerprint_success">Vingerafdruk herkend</string>
- <string name="new_fingerprint_enrolled_description">Er werd een nieuwe vingerafdruk aan dit apparaat toegevoegd, waardoor uw wachtwoord is vereist.</string>
- <string name="secure_lock_screen_required">Beveiligd vergrendelingsscherm vereist!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Cancelar</string>
- <string name="fingerprint_use_backup">Use o backup</string>
- <string name="fingerprint_auth_dialog_title">Autenticação de impressão digital</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Confirme a impressão digital para continuar</string>
- <string name="fingerprint_hint">Sensor de toque</string>
- <string name="fingerprint_not_recognized">impressão digital não reconhecida. Tente novamente.</string>
- <string name="fingerprint_success">impressão digital reconhecida</string>
- <string name="new_fingerprint_enrolled_description">Uma nova impressão digital foi adicionada a este dispositivo, é necessário o seu código</string>
- <string name="secure_lock_screen_required">É necessário um ecrã de bloqueio seguro!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">取消</string>
- <string name="fingerprint_use_backup">使用手勢密碼</string>
- <string name="fingerprint_auth_dialog_title">指紋識別</string>
- <string name="fingerprint_ok">確認</string><string name="fingerprint_description">指紋識別</string>
- <string name="fingerprint_hint">請觸摸指紋識別傳感器</string>
- <string name="fingerprint_not_recognized">指紋無法識別,請再試一次</string>
- <string name="fingerprint_success">指紋識別成功</string>
- <string name="new_fingerprint_enrolled_description">添加一個新的指紋,需要設置密碼</string>
- <string name="secure_lock_screen_required">需要安全鎖屏</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">取消</string>
- <string name="fingerprint_use_backup">使用手势密码</string>
- <string name="fingerprint_auth_dialog_title">指纹识别</string>
- <string name="fingerprint_ok">确认</string><string name="fingerprint_description">指纹识别</string>
- <string name="fingerprint_hint">请触摸指纹识传感器</string>
- <string name="fingerprint_not_recognized">指纹无法识别,请再试一次</string>
- <string name="fingerprint_success">指纹识别成功</string>
- <string name="new_fingerprint_enrolled_description">添加一个新的指纹,需要设置密码</string>
- <string name="secure_lock_screen_required">需要安全锁屏</string>
-</resources>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <style name="TransparentTheme" parent="Theme.AppCompat">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ </style>
+</resources>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <color name="warning_color">#f4511e</color>
- <color name="hint_color">#42000000</color>
- <color name="success_color">#009688</color>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Cancel</string>
- <string name="fingerprint_use_backup">Use backup</string>
- <string name="fingerprint_auth_dialog_title">Fingerprint Authentication</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Confirm fingerprint to continue</string>
- <string name="fingerprint_hint">Touch sensor</string>
- <string name="fingerprint_not_recognized">Fingerprint not recognized. Try again.</string>
- <string name="fingerprint_success">Fingerprint recognized</string>
- <string name="new_fingerprint_enrolled_description">A new fingerprint was added to this device, so your password is required.</string>
- <string name="secure_lock_screen_required">Secure lock screen required!</string>
-</resources>
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.dalicitycard.app" version="1.0.6" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
- <feature name="Fingerprint">
- <param name="android-package" value="de.niklasmerz.cordova.fingerprint.Fingerprint" />
- </feature>
<feature name="Whitelist">
<param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
<param name="onload" value="true" />
<feature name="Brightness">
<param name="android-package" value="org.apache.cordova.plugin.Brightness.BrightnessPlugin" />
</feature>
+ <feature name="Fingerprint">
+ <param name="android-package" value="de.niklasmerz.cordova.biometric.Fingerprint" />
+ </feature>
<name short="大理市民卡">dlapp</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
--- /dev/null
+allprojects {
+ repositories {
+ maven { url 'https://jitpack.io' }
+ }
+}
+
+dependencies {
+
+ /**
+ * The android-biometric.aar file has been taken from com.github.exxbrain:android-biometric library.
+ * Android biometric library is a clone of androidx.biometric library adapted for non-androidx apps.
+ * This project could be found at https://github.com/exxbrain/android-biometric.
+ * It has Apache License 2.0.
+ *
+ * TODO: Temporary solution. Should be removed after moving cordova-android to androidx. Then use androidx.biometric.
+ */
+ implementation 'com.github.exxbrain:android-biometric:0.4'
+
+ implementation 'com.android.support:design:28.0.0'
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support:support-v4:28.0.0'
+ implementation 'com.android.support:support-annotations:28.0.0'
+}
+
+android {
+ packagingOptions {
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/LICENSE'
+ }
+}
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
- {
- "id": "cordova-plugin-fingerprint-aio.Fingerprint",
- "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
- "pluginId": "cordova-plugin-fingerprint-aio",
- "clobbers": [
- "Fingerprint"
- ]
- },
{
"id": "cordova-plugin-touch-id.TouchID",
"file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
]
},
{
- "id": "cordova-plugin-file-opener2.FileOpener2",
- "file": "plugins/cordova-plugin-file-opener2/www/plugins.FileOpener2.js",
- "pluginId": "cordova-plugin-file-opener2",
- "clobbers": [
- "cordova.plugins.fileOpener2"
- ]
- },
- {
- "id": "cordova-plugin-file-transfer.FileTransferError",
- "file": "plugins/cordova-plugin-file-transfer/www/FileTransferError.js",
- "pluginId": "cordova-plugin-file-transfer",
- "clobbers": [
- "window.FileTransferError"
- ]
- },
- {
- "id": "cordova-plugin-file-transfer.FileTransfer",
- "file": "plugins/cordova-plugin-file-transfer/www/FileTransfer.js",
- "pluginId": "cordova-plugin-file-transfer",
- "clobbers": [
- "window.FileTransfer"
- ]
- },
- {
- "id": "cordova-plugin-crop.CropPlugin",
- "file": "plugins/cordova-plugin-crop/www/crop.js",
- "pluginId": "cordova-plugin-crop",
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "pluginId": "cordova-plugin-fingerprint-aio",
"clobbers": [
- "plugins.crop"
+ "Fingerprint"
]
}
];
module.exports.metadata = {
"cordova-plugin-add-swift-support": "2.0.2",
- "cordova-plugin-fingerprint-aio": "1.7.0",
"cordova-plugin-touch-id": "3.3.1",
"cordova-plugin-whitelist": "1.3.3",
"cordova-plugin-file": "6.0.1",
"cordova-plugin-app-version": "0.1.9",
"cordova-plugin-wkwebview-engine": "1.2.1",
"cordova-plugin-brightness": "0.1.5",
- "cordova-plugin-file-opener2": "2.2.1",
- "cordova-plugin-file-transfer": "1.7.1",
- "cordova-plugin-crop": "0.3.1"
+ "cordova-plugin-fingerprint-aio": "3.0.1"
};
});
\ No newline at end of file
cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) {
/*global cordova */
-function Fingerprint() {
-}
+var Fingerprint = function() {
+};
+
+// Plugin Errors
+Fingerprint.prototype.BIOMETRIC_UNKNOWN_ERROR = -100;
+Fingerprint.prototype.BIOMETRIC_UNAVAILABLE = -101;
+Fingerprint.prototype.BIOMETRIC_AUTHENTICATION_FAILED = -102;
+Fingerprint.prototype.BIOMETRIC_SDK_NOT_SUPPORTED = -103;
+Fingerprint.prototype.BIOMETRIC_HARDWARE_NOT_SUPPORTED = -104;
+Fingerprint.prototype.BIOMETRIC_PERMISSION_NOT_GRANTED = -105;
+Fingerprint.prototype.BIOMETRIC_NOT_ENROLLED = -106;
+Fingerprint.prototype.BIOMETRIC_INTERNAL_PLUGIN_ERROR = -107;
+Fingerprint.prototype.BIOMETRIC_DISMISSED = -108;
+Fingerprint.prototype.BIOMETRIC_PIN_OR_PATTERN_DISMISSED = -109;
+Fingerprint.prototype.BIOMETRIC_SCREEN_GUARD_UNSECURED = -110;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT = -111;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT_PERMANENT = -112;
+
+// Biometric types
+Fingerprint.prototype.BIOMETRIC_TYPE_FINGERPRINT = "finger";
+Fingerprint.prototype.BIOMETRIC_TYPE_FACE = "face";
+Fingerprint.prototype.BIOMETRIC_TYPE_COMMON = "biometric";
Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
cordova.exec(
cordova.system.library.1=com.squareup.okhttp3:okhttp-urlconnection:3.10.0
cordova.gradle.include.1=cordova-plugin-qrscanner/dlapp-qrscanner.gradle
cordova.system.library.2=com.android.support:support-v4:24.1.1+
+cordova.gradle.include.2=cordova-plugin-fingerprint-aio/app-build.gradle
\ No newline at end of file
"cordova-plugin-add-swift-support": {
"PACKAGE_NAME": "com.supwisdom.dlapp"
},
- "cordova-plugin-fingerprint-aio": {
- "PACKAGE_NAME": "com.supwisdom.dlapp"
- },
"cordova-plugin-touch-id": {
"PACKAGE_NAME": "com.supwisdom.dlapp"
},
},
"cordova-plugin-brightness": {
"PACKAGE_NAME": "com.dalicitycard.app"
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "PACKAGE_NAME": "com.dalicitycard.app"
}
},
"dependent_plugins": {},
"modules": [
- {
- "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
- "id": "cordova-plugin-fingerprint-aio.Fingerprint",
- "pluginId": "cordova-plugin-fingerprint-aio",
- "clobbers": [
- "Fingerprint"
- ]
- },
{
"file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
"id": "cordova-plugin-touch-id.TouchID",
"clobbers": [
"cordova.plugins.brightness"
]
+ },
+ {
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "pluginId": "cordova-plugin-fingerprint-aio",
+ "clobbers": [
+ "Fingerprint"
+ ]
}
],
"plugin_metadata": {
"cordova-plugin-add-swift-support": "2.0.2",
- "cordova-plugin-fingerprint-aio": "1.7.0",
"cordova-plugin-touch-id": "3.3.1",
"cordova-plugin-whitelist": "1.3.3",
"cordova-plugin-file": "6.0.1",
"jpush-phonegap-plugin": "3.7.2",
"cordova-plugin-app-version": "0.1.9",
"cordova-plugin-wkwebview-engine": "1.2.1",
- "cordova-plugin-brightness": "0.1.5"
+ "cordova-plugin-brightness": "0.1.5",
+ "cordova-plugin-fingerprint-aio": "3.0.1"
}
}
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
- {
- "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
- "id": "cordova-plugin-fingerprint-aio.Fingerprint",
- "pluginId": "cordova-plugin-fingerprint-aio",
- "clobbers": [
- "Fingerprint"
- ]
- },
{
"file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
"id": "cordova-plugin-touch-id.TouchID",
"clobbers": [
"cordova.plugins.brightness"
]
+ },
+ {
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "pluginId": "cordova-plugin-fingerprint-aio",
+ "clobbers": [
+ "Fingerprint"
+ ]
}
];
module.exports.metadata =
// TOP OF METADATA
{
"cordova-plugin-add-swift-support": "2.0.2",
- "cordova-plugin-fingerprint-aio": "1.7.0",
"cordova-plugin-touch-id": "3.3.1",
"cordova-plugin-whitelist": "1.3.3",
"cordova-plugin-file": "6.0.1",
"jpush-phonegap-plugin": "3.7.2",
"cordova-plugin-app-version": "0.1.9",
"cordova-plugin-wkwebview-engine": "1.2.1",
- "cordova-plugin-brightness": "0.1.5"
+ "cordova-plugin-brightness": "0.1.5",
+ "cordova-plugin-fingerprint-aio": "3.0.1"
}
// BOTTOM OF METADATA
});
\ No newline at end of file
cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) { /*global cordova */
-function Fingerprint() {
-}
+var Fingerprint = function() {
+};
+
+// Plugin Errors
+Fingerprint.prototype.BIOMETRIC_UNKNOWN_ERROR = -100;
+Fingerprint.prototype.BIOMETRIC_UNAVAILABLE = -101;
+Fingerprint.prototype.BIOMETRIC_AUTHENTICATION_FAILED = -102;
+Fingerprint.prototype.BIOMETRIC_SDK_NOT_SUPPORTED = -103;
+Fingerprint.prototype.BIOMETRIC_HARDWARE_NOT_SUPPORTED = -104;
+Fingerprint.prototype.BIOMETRIC_PERMISSION_NOT_GRANTED = -105;
+Fingerprint.prototype.BIOMETRIC_NOT_ENROLLED = -106;
+Fingerprint.prototype.BIOMETRIC_INTERNAL_PLUGIN_ERROR = -107;
+Fingerprint.prototype.BIOMETRIC_DISMISSED = -108;
+Fingerprint.prototype.BIOMETRIC_PIN_OR_PATTERN_DISMISSED = -109;
+Fingerprint.prototype.BIOMETRIC_SCREEN_GUARD_UNSECURED = -110;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT = -111;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT_PERMANENT = -112;
+
+// Biometric types
+Fingerprint.prototype.BIOMETRIC_TYPE_FINGERPRINT = "finger";
+Fingerprint.prototype.BIOMETRIC_TYPE_FACE = "face";
+Fingerprint.prototype.BIOMETRIC_TYPE_COMMON = "biometric";
Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
cordova.exec(
};
objectVersion = 46;
objects = {
-
/* Begin PBXBuildFile section */
0207DA581B56EA530066E2B4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0207DA571B56EA530066E2B4 /* Images.xcassets */; };
04347BD0ABAC4EE0B4CDDDB6 /* jcore-ios-2.1.1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 444DBF371D8346D7BC7EE35D /* jcore-ios-2.1.1.a */; };
A42AE846FF7B482FB889AAEB /* QRScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8478FFD487C4004A1CEFCA8 /* QRScanner.swift */; };
A50EB04ADB24A5CBB680802F /* libPods-dlapp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D992375F52889311A88544EF /* libPods-dlapp.a */; };
A54A9FED843144C887EA4286 /* AppDelegate+JPush.m in Sources */ = {isa = PBXBuildFile; fileRef = 91E044FC8377488C886C818B /* AppDelegate+JPush.m */; };
- B69FF513D1EE4772AFF6050B /* Fingerprint.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2099240B64744E08C91C285 /* Fingerprint.swift */; };
B8EFB66D03A44372A240B05B /* CDVCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 80B448E71F8941268B78692C /* CDVCamera.m */; };
BC39BA77AF0D4F94BC27666A /* CDVDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = A50DE9801E5E4302A78D569C /* CDVDevice.m */; };
BC998F935D174204820F4015 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 22AE2683802B4CB1BAF69ABF /* AFURLSessionManager.m */; };
F68EA21E51A3463A8FE2EE92 /* CDVWKWebViewUIDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B73EA28E46846FF84E6AF02 /* CDVWKWebViewUIDelegate.m */; };
F939AD8D22BB769B006B371B /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F939AD8C22BB769B006B371B /* libsqlite3.0.tbd */; };
FDE92C386167415E8040F8AB /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = FDEE8379D7A34C55A616F700 /* AFURLResponseSerialization.m */; };
+ 81B8C05354704A02AE1560A0 /* Fingerprint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39BDB5993A0D495C9E97E995 /* Fingerprint.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
B3CE13EED96B44C0B06B1B2C /* TouchID.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = TouchID.m; path = "cordova-plugin-touch-id/TouchID.m"; sourceTree = "<group>"; };
B3F9D30FB27A4B26A445BA84 /* CDVExif.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVExif.h; path = "cordova-plugin-camera/CDVExif.h"; sourceTree = "<group>"; };
BA6C5B1A6A6A488790CA41EB /* AFSecurityPolicy.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = "cordova-plugin-advanced-http/AFSecurityPolicy.m"; sourceTree = "<group>"; };
- C2099240B64744E08C91C285 /* Fingerprint.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = Fingerprint.swift; path = "cordova-plugin-fingerprint-aio/Fingerprint.swift"; sourceTree = "<group>"; };
C44E29C3B190445C98BBAB84 /* CoreFoundation.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
C8478FFD487C4004A1CEFCA8 /* QRScanner.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = QRScanner.swift; path = "cordova-plugin-qrscanner/QRScanner.swift"; sourceTree = "<group>"; };
CBD6EA74C612474DA862E146 /* libresolv.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
F840E1F0165FE0F500CFE078 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = dlapp/config.xml; sourceTree = "<group>"; };
F939AD8C22BB769B006B371B /* libsqlite3.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; };
FC8EA7F3637547AD8BC62127 /* JPushDefine.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = JPushDefine.h; path = "jpush-phonegap-plugin/JPushDefine.h"; sourceTree = "<group>"; };
- FCC7E279D80D4FB9BCF2530A /* Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "Bridging-Header.h"; path = "cordova-plugin-fingerprint-aio/Bridging-Header.h"; sourceTree = "<group>"; };
FDEE8379D7A34C55A616F700 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = "cordova-plugin-advanced-http/AFURLResponseSerialization.m"; sourceTree = "<group>"; };
FE0B455916A4481681D59FE0 /* WebKit.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
+ 39BDB5993A0D495C9E97E995 /* Fingerprint.swift */ = {isa = PBXFileReference; name = "Fingerprint.swift"; path = "cordova-plugin-fingerprint-aio/Fingerprint.swift"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.swift; explicitFileType = undefined; includeInIndex = 0; };
+ 705239B1B7D9402DA8A9FDA7 /* Bridging-Header.h */ = {isa = PBXFileReference; name = "Bridging-Header.h"; path = "cordova-plugin-fingerprint-aio/Bridging-Header.h"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
3BE5364CD5E74AFDAB853364 /* AFURLResponseSerialization.h */,
7E931FBE72E74C4887498E5F /* AFURLSessionManager.h */,
D4DBE4512BAD4694B7EB5217 /* SDNetworkActivityIndicator.h */,
- C2099240B64744E08C91C285 /* Fingerprint.swift */,
- FCC7E279D80D4FB9BCF2530A /* Bridging-Header.h */,
1ABBE12B040548F8909BFC7B /* CDVStatusBar.m */,
8BFF0D502E2241F0A89DF67F /* CDVStatusBar.h */,
B3CE13EED96B44C0B06B1B2C /* TouchID.m */,
7DC7711D3C76485B9E422E3A /* CDVWKProcessPoolFactory.h */,
1E4D2B8A1F474D9883C50B86 /* Brightness.m */,
817A61F7D48245FA9567B115 /* Brightness.h */,
+ 39BDB5993A0D495C9E97E995 /* Fingerprint.swift */,
+ 705239B1B7D9402DA8A9FDA7 /* Bridging-Header.h */,
);
name = Plugins;
path = dlapp/Plugins;
FDE92C386167415E8040F8AB /* AFURLResponseSerialization.m in Sources */,
BC998F935D174204820F4015 /* AFURLSessionManager.m in Sources */,
D404D18DD0114DA787E0BB43 /* SDNetworkActivityIndicator.m in Sources */,
- B69FF513D1EE4772AFF6050B /* Fingerprint.swift in Sources */,
CAE5A91F948A472F9D872EC8 /* CDVStatusBar.m in Sources */,
D834895F80744E0F96D59047 /* TouchID.m in Sources */,
C61263FC7FE642E9B25A81E5 /* DisableStatusbar.m in Sources */,
F68EA21E51A3463A8FE2EE92 /* CDVWKWebViewUIDelegate.m in Sources */,
1F969D21D7EF4CF1A547A1DF /* CDVWKProcessPoolFactory.m in Sources */,
C0A6FD40F47B434496535606 /* Brightness.m in Sources */,
+ 81B8C05354704A02AE1560A0 /* Fingerprint.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
import Foundation
import LocalAuthentication
+
@objc(Fingerprint) class Fingerprint : CDVPlugin {
+ enum PluginError:Int {
+ case BIOMETRIC_UNKNOWN_ERROR = -100
+ case BIOMETRIC_UNAVAILABLE = -101
+ case BIOMETRIC_AUTHENTICATION_FAILED = -102
+ case BIOMETRIC_PERMISSION_NOT_GRANTED = -105
+ case BIOMETRIC_NOT_ENROLLED = -106
+ case BIOMETRIC_DISMISSED = -108
+ case BIOMETRIC_SCREEN_GUARD_UNSECURED = -110
+ case BIOMETRIC_LOCKED_OUT = -111
+ }
+
+ struct ErrorCodes {
+ var code: Int
+ }
+
+
@objc(isAvailable:)
func isAvailable(_ command: CDVInvokedUrlCommand){
let authenticationContext = LAContext();
var biometryType = "finger";
+ var errorResponse: [AnyHashable: Any] = [
+ "code": 0,
+ "message": "Not Available"
+ ];
var error:NSError?;
let policy:LAPolicy = .deviceOwnerAuthenticationWithBiometrics;
-
+ var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Not available");
let available = authenticationContext.canEvaluatePolicy(policy, error: &error);
+ var results: [String : Any]
+
if(error != nil){
biometryType = "none";
+ errorResponse["code"] = error?.code;
+ errorResponse["message"] = error?.localizedDescription;
}
- var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Not available");
- if available == true {
+ if (available == true) {
if #available(iOS 11.0, *) {
switch(authenticationContext.biometryType) {
case .none:
}
pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: biometryType);
+ }else{
+ var code: Int;
+ switch(error!._code) {
+ case Int(kLAErrorBiometryNotAvailable):
+ code = PluginError.BIOMETRIC_UNAVAILABLE.rawValue;
+ break;
+ case Int(kLAErrorBiometryNotEnrolled):
+ code = PluginError.BIOMETRIC_NOT_ENROLLED.rawValue;
+ break;
+
+ default:
+ code = PluginError.BIOMETRIC_UNKNOWN_ERROR.rawValue;
+ break;
+ }
+ results = ["code": code, "message": error!.localizedDescription];
+ pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: results);
}
commandDelegate.send(pluginResult, callbackId:command.callbackId);
@objc(authenticate:)
func authenticate(_ command: CDVInvokedUrlCommand){
let authenticationContext = LAContext();
- var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Something went wrong");
+ var errorResponse: [AnyHashable: Any] = [
+ "message": "Something went wrong"
+ ];
+ var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: errorResponse);
var reason = "Authentication";
var policy:LAPolicy = .deviceOwnerAuthentication;
let data = command.arguments[0] as AnyObject?;
authenticationContext.localizedFallbackTitle = "";
policy = .deviceOwnerAuthenticationWithBiometrics;
} else {
- if let localizedFallbackTitle = data?["localizedFallbackTitle"] as! String? {
- authenticationContext.localizedFallbackTitle = localizedFallbackTitle;
+ if let fallbackButtonTitle = data?["fallbackButtonTitle"] as! String? {
+ authenticationContext.localizedFallbackTitle = fallbackButtonTitle;
+ }else{
+ authenticationContext.localizedFallbackTitle = "Use Pin";
}
}
}
// Localized reason
- if let localizedReason = data?["localizedReason"] as! String? {
- reason = localizedReason;
- }else if let clientId = data?["clientId"] as! String? {
- reason = clientId;
+ if let description = data?["description"] as! String? {
+ reason = description;
}
authenticationContext.evaluatePolicy(
if( success ) {
pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: "Success");
}else {
- // Check if there is an error
- if error != nil {
- pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Error: \(String(describing: error?.localizedDescription))")
+ if (error != nil) {
+
+ var errorCodes = [Int: ErrorCodes]()
+ var errorResult: [String : Any] = ["code": PluginError.BIOMETRIC_UNKNOWN_ERROR.rawValue, "message": error?.localizedDescription ?? ""];
+
+ errorCodes[1] = ErrorCodes(code: PluginError.BIOMETRIC_AUTHENTICATION_FAILED.rawValue)
+ errorCodes[2] = ErrorCodes(code: PluginError.BIOMETRIC_DISMISSED.rawValue)
+ errorCodes[5] = ErrorCodes(code: PluginError.BIOMETRIC_SCREEN_GUARD_UNSECURED.rawValue)
+ errorCodes[6] = ErrorCodes(code: PluginError.BIOMETRIC_UNAVAILABLE.rawValue)
+ errorCodes[7] = ErrorCodes(code: PluginError.BIOMETRIC_NOT_ENROLLED.rawValue)
+ errorCodes[8] = ErrorCodes(code: PluginError.BIOMETRIC_LOCKED_OUT.rawValue)
+
+ let errorCode = abs(error!._code)
+ if let e = errorCodes[errorCode] {
+ errorResult = ["code": e.code, "message": error!.localizedDescription];
+ }
+
+ pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: errorResult);
}
}
self.commandDelegate.send(pluginResult, callbackId:command.callbackId);
- });
+ }
+ );
}
override func pluginInitialize() {
super.pluginInitialize()
}
-}
-
+}
\ No newline at end of file
<feature name="CordovaHttpPlugin">
<param name="ios-package" value="CordovaHttpPlugin" />
</feature>
- <feature name="Fingerprint">
- <param name="ios-package" value="Fingerprint" />
- </feature>
<feature name="StatusBar">
<param name="ios-package" value="CDVStatusBar" />
<param name="onload" value="true" />
<feature name="Brightness">
<param name="ios-package" value="Brightness" />
</feature>
+ <feature name="Fingerprint">
+ <param name="ios-package" value="Fingerprint" />
+ </feature>
<name short="大理市民卡">dlapp</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
"xml": "<feature name=\"CordovaHttpPlugin\"><param name=\"ios-package\" value=\"CordovaHttpPlugin\" /></feature>",
"count": 1
},
- {
- "xml": "<feature name=\"Fingerprint\"><param name=\"ios-package\" value=\"Fingerprint\" /></feature>",
- "count": 1
- },
{
"xml": "<feature name=\"StatusBar\"><param name=\"ios-package\" value=\"CDVStatusBar\" /><param name=\"onload\" value=\"true\" /></feature>",
"count": 1
{
"xml": "<feature name=\"Brightness\"><param name=\"ios-package\" value=\"Brightness\" /></feature>",
"count": 1
+ },
+ {
+ "xml": "<feature name=\"Fingerprint\"><param name=\"ios-package\" value=\"Fingerprint\" /></feature>",
+ "count": 1
}
]
}
"*-Info.plist": {
"parents": {
"NSFaceIDUsageDescription": [
- {
- "xml": "<string>认证中...</string>",
- "count": 1
- },
{
"xml": "<string> </string>",
- "count": 1
+ "count": 2
}
],
"NSCameraUsageDescription": [
"cordova-plugin-advanced-http": {
"PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
},
- "cordova-plugin-fingerprint-aio": {
- "FACEID_USAGE_DESCRIPTION": "认证中...",
- "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
- },
"cordova-plugin-statusbar": {
"PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
},
},
"cordova-plugin-brightness": {
"PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "FACEID_USAGE_DESCRIPTION": " ",
+ "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
}
},
"dependent_plugins": {},
"cordova.plugin.http"
]
},
- {
- "id": "cordova-plugin-fingerprint-aio.Fingerprint",
- "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
- "pluginId": "cordova-plugin-fingerprint-aio",
- "clobbers": [
- "Fingerprint"
- ]
- },
{
"id": "cordova-plugin-statusbar.statusbar",
"file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
"clobbers": [
"cordova.plugins.brightness"
]
+ },
+ {
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "pluginId": "cordova-plugin-fingerprint-aio",
+ "clobbers": [
+ "Fingerprint"
+ ]
}
],
"plugin_metadata": {
"cordova-plugin-add-swift-support": "2.0.2",
"cordova-plugin-file": "6.0.1",
"cordova-plugin-advanced-http": "2.1.1",
- "cordova-plugin-fingerprint-aio": "1.7.0",
"cordova-plugin-statusbar": "2.4.2",
"cordova-plugin-touch-id": "3.3.1",
"cordova-plugin-whitelist": "1.3.3",
"jpush-phonegap-plugin": "3.7.2",
"cordova-plugin-app-version": "0.1.9",
"cordova-plugin-wkwebview-engine": "1.2.1",
- "cordova-plugin-brightness": "0.1.5"
+ "cordova-plugin-brightness": "0.1.5",
+ "cordova-plugin-fingerprint-aio": "3.0.1"
}
}
"cordova.plugin.http"
]
},
- {
- "id": "cordova-plugin-fingerprint-aio.Fingerprint",
- "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
- "pluginId": "cordova-plugin-fingerprint-aio",
- "clobbers": [
- "Fingerprint"
- ]
- },
{
"id": "cordova-plugin-statusbar.statusbar",
"file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
"clobbers": [
"cordova.plugins.brightness"
]
+ },
+ {
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "pluginId": "cordova-plugin-fingerprint-aio",
+ "clobbers": [
+ "Fingerprint"
+ ]
}
];
module.exports.metadata = {
"cordova-plugin-add-swift-support": "2.0.2",
"cordova-plugin-file": "6.0.1",
"cordova-plugin-advanced-http": "2.1.1",
- "cordova-plugin-fingerprint-aio": "1.7.0",
"cordova-plugin-statusbar": "2.4.2",
"cordova-plugin-touch-id": "3.3.1",
"cordova-plugin-whitelist": "1.3.3",
"jpush-phonegap-plugin": "3.7.2",
"cordova-plugin-app-version": "0.1.9",
"cordova-plugin-wkwebview-engine": "1.2.1",
- "cordova-plugin-brightness": "0.1.5"
+ "cordova-plugin-brightness": "0.1.5",
+ "cordova-plugin-fingerprint-aio": "3.0.1"
};
});
\ No newline at end of file
cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) {
/*global cordova */
-function Fingerprint() {
-}
+var Fingerprint = function() {
+};
+
+// Plugin Errors
+Fingerprint.prototype.BIOMETRIC_UNKNOWN_ERROR = -100;
+Fingerprint.prototype.BIOMETRIC_UNAVAILABLE = -101;
+Fingerprint.prototype.BIOMETRIC_AUTHENTICATION_FAILED = -102;
+Fingerprint.prototype.BIOMETRIC_SDK_NOT_SUPPORTED = -103;
+Fingerprint.prototype.BIOMETRIC_HARDWARE_NOT_SUPPORTED = -104;
+Fingerprint.prototype.BIOMETRIC_PERMISSION_NOT_GRANTED = -105;
+Fingerprint.prototype.BIOMETRIC_NOT_ENROLLED = -106;
+Fingerprint.prototype.BIOMETRIC_INTERNAL_PLUGIN_ERROR = -107;
+Fingerprint.prototype.BIOMETRIC_DISMISSED = -108;
+Fingerprint.prototype.BIOMETRIC_PIN_OR_PATTERN_DISMISSED = -109;
+Fingerprint.prototype.BIOMETRIC_SCREEN_GUARD_UNSECURED = -110;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT = -111;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT_PERMANENT = -112;
+
+// Biometric types
+Fingerprint.prototype.BIOMETRIC_TYPE_FINGERPRINT = "finger";
+Fingerprint.prototype.BIOMETRIC_TYPE_FACE = "face";
+Fingerprint.prototype.BIOMETRIC_TYPE_COMMON = "biometric";
Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
cordova.exec(
"files": {}
},
"installed_plugins": {
- "cordova-plugin-fingerprint-aio": {
- "PACKAGE_NAME": "com.supwisdom.dlapp"
- },
"cordova-plugin-touch-id": {
"PACKAGE_NAME": "com.supwisdom.dlapp"
},
},
"cordova-plugin-file": {
"PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "PACKAGE_NAME": "com.dalicitycard.app"
}
},
"dependent_plugins": {
"files": {}
},
"installed_plugins": {
- "cordova-plugin-fingerprint-aio": {
- "PACKAGE_NAME": "com.supwisdom.dlapp"
- },
"cordova-plugin-touch-id": {
"PACKAGE_NAME": "com.supwisdom.dlapp"
},
},
"cordova-plugin-file": {
"PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "PACKAGE_NAME": "com.dalicitycard.app"
}
},
"dependent_plugins": {
+# This Travis configuration file is built after a Cordova Paramedic
+# specific template with minimal modifications and adaptations:
+# https://github.com/apache/cordova-paramedic/blob/master/.travis.yml
+
sudo: false
addons:
jwt:
secure: f0G7Z/0N1ACi5pFg32P4kr8tVd5EOADDne5a8/MtabGTjeH0/QZl+4xKIgemXle6BJn949Gqpx4+XkmaKmDHHfIsV+9GmLwqGpGSyQMMoeBI0Lfxzh8aecYDxfJKBYmdmpJcyG3yKa42nxQFEMIljf0NJEmNN8AAglsaSh5VQq2dlv1aXaoJz18dpgRVE1cJ4rvUJN+fOrZYjRsqw9ev+11J7cwRONsBB/Yx+56tsverD2uC4Xutj58CEaw7WRk4BLMqehkGO0/ez2Ofc9dBDfc4ZHqHxZMfqjYO5r95VFclyIgto9ToW2kazuK+NZMgaX5wEBp+ktVQGHQw+rRunANplJt14AXpu7Elpfp04Hb4qjBQTYCXellNJ1TgLJLhP6a3P4nTUBrZ9I5mjSGI8ckvUEb1066KyGJmMIPs64z6BJgDHd91PP+cDq6MqUm+n+m24l6Ou/iLDmxaEs6peEctx5A6hACnNwyyB5MEeqZVbksFkNoYw9pxbTj1bBtBbg5QRHC7+Bd8mrN12VOi2wA2N8dFgO3Np+sfZriq/CXfCPrDNYPX8IwF9HEkm2J+PLW1MD8Kx2XwALCqKjU6md0hKui5LdhNWlpAiNK/eBLtJEF2egaMkQw1JPQYxHIyAAi4yUSYYVd64hb9rgUSTNiywRddmKovBChiwiTsmFc=
env:
global:
- - SAUCE_USERNAME=NiklasMerz
- - TRAVIS_NODE_VERSION="lts/*"
+ - SAUCE_USERNAME=NiklasMerz
+ - TRAVIS_NODE_VERSION=8
+ - ANDROID_API_LEVEL=28
+ - ANDROID_BUILD_TOOLS_VERSION=28.0.3
+
+language: node_js
+node_js: 8
+
+# yaml anchor/alias: https://medium.com/@tommyvn/travis-yml-dry-with-anchors-8b6a3ac1b027
+
+_ios: &_ios
+ os: osx
+ osx_image: xcode10.2
+
+_android: &_android
+ language: android
+ os: linux
+ jdk: oraclejdk8
+ android:
+ components:
+ - tools
+ - build-tools-$ANDROID_BUILD_TOOLS_VERSION
+ - android-$ANDROID_API_LEVEL
+ licenses:
+ - 'android-sdk-preview-license-.+'
+ - 'android-sdk-license-.+'
+ - 'google-gdk-license-.+'
+
matrix:
include:
- - env: PLATFORM=android-7.0
- os: linux
- language: android
- jdk: oraclejdk8
- android:
- components:
- - tools
- - build-tools-26.0.2
- - env: PLATFORM=ios-10.0
- os: osx
- osx_image: xcode9.2
- language: node_js
- node_js: 'lts/*'
+ # local tests, without saucelabs
+ - env: PLATFORM=local/ios-10.0
+ <<: *_ios
+
+ # many tests with saucelabs
+
+ - env: PLATFORM=ios-11.3
+ <<: *_ios
+ - env: PLATFORM=ios-12.0
+ <<: *_ios
+
+ - env: PLATFORM=android-8.1
+ <<: *_android
+ - env: PLATFORM=android-9.0
+ <<: *_android
+
before_install:
-- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm
- && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm
- install $TRAVIS_NODE_VERSION
-- node --version
-- if [[ "$PLATFORM" =~ android ]]; then gradle --version; fi
-- if [[ "$PLATFORM" =~ ios ]]; then npm install -g ios-deploy; fi
-- if [[ "$PLATFORM" =~ android ]]; then echo y | android update sdk -u --filter android-25,android-26;
- fi
-- git clone https://github.com/apache/cordova-paramedic /tmp/paramedic && pushd /tmp/paramedic
- && npm install && popd
-- npm install -g cordova@7.0.1
+ # manually install Node for `language: android`
+ - if [[ "$PLATFORM" =~ android ]]; then nvm install $TRAVIS_NODE_VERSION; fi
+ - node --version
+ - if [[ "$PLATFORM" =~ android ]]; then gradle --version; fi
+ - if [[ "$PLATFORM" =~ ios ]]; then npm install -g ios-deploy; fi
+ - npm install -g cordova
+ # install paramedic if not running on paramedic repo
+ - if ! [[ "$TRAVIS_REPO_SLUG" =~ cordova-paramedic ]]; then npm install -g github:apache/cordova-paramedic; fi
+
install:
-- npm install
+ - npm install
+
+before_script:
+ - |
+ if [[ "$TRAVIS_REPO_SLUG" =~ cordova-paramedic ]]; then
+ # when used in the cordova-paramedic repo
+ TEST_COMMAND="npm run eslint"
+ PARAMEDIC_PLUGIN_TO_TEST="./spec/testable-plugin/"
+ PARAMEDIC_COMMAND="node main.js"
+ else
+ # when used in any other (plugin) repo
+ TEST_COMMAND="npm test"
+ PARAMEDIC_PLUGIN_TO_TEST=$(pwd)
+ PARAMEDIC_COMMAND="cordova-paramedic"
+ fi
+ - PARAMEDIC_BUILDNAME=travis-$TRAVIS_REPO_SLUG-$TRAVIS_JOB_NUMBER
+ - |
+ echo "Variables now are set to:"
+ echo "TEST_COMMAND=$TEST_COMMAND"
+ echo "ADDITIONAL_TESTS=$ADDITIONAL_TESTS"
+ echo "PARAMEDIC_COMMAND=$PARAMEDIC_COMMAND"
+ echo "PLATFORM=$PLATFORM"
+ echo "PARAMEDIC_PLUGIN_TO_TEST=$PARAMEDIC_PLUGIN_TO_TEST"
+ echo "PARAMEDIC_BUILDNAME=$PARAMEDIC_BUILDNAME"
script:
-- node /tmp/paramedic/main.js --config pr/$PLATFORM --plugin $(pwd) --shouldUseSauce
- --buildName travis-plugin-fingerprint-aio-$TRAVIS_JOB_NUMBER
+ - $TEST_COMMAND
+ - if [[ "$ADDITIONAL_TESTS_DIR" != "" ]]; then
+ cd $ADDITIONAL_TESTS_DIR && npm install && npm test;
+ else
+ $PARAMEDIC_COMMAND --config ./pr/$PLATFORM --plugin $PARAMEDIC_PLUGIN_TO_TEST --buildName $PARAMEDIC_BUILDNAME;
+ fi
notifications:
email: false
slack:
* Android - Minimum SDK 23
* iOS - **XCode 9.2 or higher** required
- * _Please set `<preference name="UseSwiftLanguageVersion" value="3.2" />` in your config.xml_
+ * _Please set `<preference name="UseSwiftLanguageVersion" value="4.0" />` in your config.xml_
## How to use
----
-
**[Tutorial about using this plugin with Ionic](https://www.youtube.com/watch?v=tQDChMJ6er8)** thanks to Paul Halliday
[Examples](https://github.com/NiklasMerz/fingerprint-aio-demo)
alert("Fingerprint available");
}
- function isAvailableError(message) {
- alert(message);
+ function isAvailableError(error) {
+ // 'error' will be an object with an error code and message
+ alert(error.message);
}
```
### Show authentication dialogue
```javascript
Fingerprint.show({
- clientId: "Fingerprint-Demo",
- clientSecret: "password" //Only necessary for Android
+ description: "Some biometric description"
}, successCallback, errorCallback);
function successCallback(){
- alert("Authentication successfull");
+ alert("Authentication successful");
}
- function errorCallback(err){
- alert("Authentication invalid " + err);
+ function errorCallback(error){
+ alert("Authentication invalid " + error.message);
}
```
-**Optional parameters**
-
-* __disableBackup__: If `true` remove backup option on authentication dialogue for Android. Default: `false`.
-* __localizedFallbackTitle__ (iOS only): Title of fallback button.
-* __localizedReason__ (iOS only): Description in authentication dialogue.
-
-## Thanks to the authors of the original fingerprint plugins
+### Optional parameters
+
+* __title__: Title in authentication dialogue. Default: `"<APP_NAME> Biometric Sign On"`
+* __subtitle__: Subtitle in authentication dialogue. Default: `null`
+* __description__: Description in authentication dialogue. Defaults:
+ * iOS: `"Authenticate"` (iOS' [evaluatePolicy()](https://developer.apple.com/documentation/localauthentication/lacontext/1514176-evaluatepolicy?language=objc) requires this field)
+ * Android: `null`
+* __fallbackButtonTitle__: Title of fallback button. Defaults:
+ * When **disableBackup** is true
+ * `"Cancel"`
+ * When **disableBackup** is false
+ * iOS: `"Use PIN"`
+ * Android: `"Use Backup"` (Because backup could be anything pin/pattern/password ..haven't figured out a reliable way to determine lock type yet [source](https://stackoverflow.com/questions/7768879/check-whether-lock-was-enabled-or-not/18720287))
+* __disableBackup__: If `true` remove backup option on authentication dialogue. Default: `false`. This is useful if you want to implement your own fallback.
+* __cancelButtonTitle__: For cancel button on Android
+
+### Constants
+- **BIOMETRIC_UNKNOWN_ERROR** = `-100`;
+- **BIOMETRIC_UNAVAILABLE** = `-101`;
+- **BIOMETRIC_AUTHENTICATION_FAILED** = `-102`;
+- **BIOMETRIC_SDK_NOT_SUPPORTED** = `-103`;
+- **BIOMETRIC_HARDWARE_NOT_SUPPORTED** = `-104`;
+- **BIOMETRIC_PERMISSION_NOT_GRANTED** = `-105`;
+- **BIOMETRIC_NOT_ENROLLED** = `-106`;
+- **BIOMETRIC_INTERNAL_PLUGIN_ERROR** = `-107`;
+- **BIOMETRIC_DISMISSED** = `-108`;
+- **BIOMETRIC_PIN_OR_PATTERN_DISMISSED** = `-109`;
+- **BIOMETRIC_SCREEN_GUARD_UNSECURED** = `-110`;
+- **BIOMETRIC_LOCKED_OUT** = `-111`;
+- **BIOMETRIC_LOCKED_OUT_PERMANENT** = `-112`;
+***
+
+Thanks to the authors of the original fingerprint plugins
Some code is refactored from their projects and I learned how to make Cordova plugins from their great plugins:
[iOS](https://github.com/EddyVerbruggen/cordova-plugin-touch-id)
+Starting with version 3.0.0 the iOS and Android parts are written from scratch.
+
## License
-* Project and iOS source: [MIT](https://opensource.org/licenses/MIT)
-* Android source: [MIT](https://opensource.org/licenses/MIT) and [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0)
+The project is MIT licensed: [MIT](https://opensource.org/licenses/MIT).
+
{
"_from": "cordova-plugin-fingerprint-aio",
- "_id": "cordova-plugin-fingerprint-aio@1.7.0",
+ "_id": "cordova-plugin-fingerprint-aio@3.0.1",
"_inBundle": false,
- "_integrity": "sha512-pV+JUeEhZUP85nXs9KMpHRClZppVHnpZA5h+8ReKBi4AV4vnzAcpUDBgFN7g3Ra83zmREYI/MqrlZlXn16pg3g==",
+ "_integrity": "sha512-Sgbv8Ykk74Ov1foEZg77owIqmHZoGktsv41rmW8KAAMf2JE93AawvQdUCYYROnk+ozG3D9ItELa5yhYU8i7Zhw==",
"_location": "/cordova-plugin-fingerprint-aio",
"_phantomChildren": {},
"_requested": {
"#USER",
"/"
],
- "_resolved": "https://registry.npmjs.org/cordova-plugin-fingerprint-aio/-/cordova-plugin-fingerprint-aio-1.7.0.tgz",
- "_shasum": "7f998587106aa47df3cb9666396b9021b6b419f7",
+ "_resolved": "https://registry.npmjs.org/cordova-plugin-fingerprint-aio/-/cordova-plugin-fingerprint-aio-3.0.1.tgz",
+ "_shasum": "030a732773e7690d74a1aadbab66c8a8b294ea42",
"_spec": "cordova-plugin-fingerprint-aio",
"_where": "/Users/shuwei/works2/cordova/dlapp",
"author": {
"devDependencies": {
"cordova-paramedic": "git+https://github.com/apache/cordova-paramedic.git",
"cordova-plugin-xml": "^0.1.2",
- "eslint": "^5.7.0",
+ "eslint": "^6.5.1",
"jasmine": "^3.2.0"
},
+ "engines": {
+ "cordovaDependencies": {
+ ">=3.0.0": {
+ "cordova-android": ">=8.0.0"
+ }
+ }
+ },
"homepage": "https://github.com/niklasmerz/cordova-plugin-fingerprint-aio#readme",
"keywords": [
"cordova",
"url": "git+https://github.com/niklasmerz/cordova-plugin-fingerprint-aio.git"
},
"scripts": {
+ "eslint": "npx eslint www",
"plugin-version": "cordova-plugin-xml setVersion",
- "test": "./node_modules/cordova-paramedic/main.js --plugin . --args=--buildFlag='-UseModernBuildSystem=0' --platform"
+ "test": "npm run eslint",
+ "test-android": "npx cordova-paramedic --platform android --plugin $(pwd)",
+ "test-appveyor": "npm run test-browser",
+ "test-browser": "npx cordova-paramedic --platform browser --plugin $(pwd)",
+ "test-ios": "npx cordova-paramedic --platform ios --plugin $(pwd) --verbose",
+ "test-local": "npm run test-browser && npm run test-android && npm run test-ios",
+ "test-saucelabs": "npm run test-saucelabs-ios && npm run test-saucelabs-android",
+ "test-saucelabs-android": "npx cordova-paramedic --config ./pr/android-7.0 --plugin $(pwd) --shouldUseSauce",
+ "test-saucelabs-ios": "npx cordova-paramedic --config ./pr/ios-10.0 --plugin $(pwd) --shouldUseSauce",
+ "test-travis": "npm run test-ios",
+ "test-windows": "npx cordova-paramedic --platform windows --plugin $(pwd)"
},
- "version": "1.7.0"
+ "version": "3.0.1"
}
<?xml version="1.0" encoding="UTF-8"?>
-<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-fingerprint-aio" version="1.7.0">
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-fingerprint-aio" version="3.0.1">
<name>FingerprintAllInOne</name>
<description>Cordova plugin to use fingerprint on Android and iOS</description>
<license>MIT</license>
<clobbers target="Fingerprint"/>
</js-module>
-
<!-- ios -->
<platform name="ios">
<param name="ios-package" value="Fingerprint"/>
</feature>
</config-file>
- <header-file src="src/ios/Bridging-Header.h" />
+ <header-file src="src/ios/Bridging-Header.h"/>
<source-file src="src/ios/Fingerprint.swift"/>
<!-- Usage description of Face ID for iOS 11+ -->
<platform name="android">
<config-file target="res/xml/config.xml" parent="/*">
<feature name="Fingerprint">
- <param name="android-package" value="de.niklasmerz.cordova.fingerprint.Fingerprint"/>
+ <param name="android-package" value="de.niklasmerz.cordova.biometric.Fingerprint"/>
</feature>
</config-file>
+
<config-file target="AndroidManifest.xml" parent="/*">
+ <uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
</config-file>
- <source-file src="src/android/Fingerprint.java" target-dir="src/de/niklasmerz/cordova/fingerprint"/>
- <source-file src="src/android/FingerprintAuthenticationDialogFragment.java" target-dir="src/de/niklasmerz/cordova/fingerprint"/>
- <source-file src="src/android/FingerprintUiHelper.java" target-dir="src/de/niklasmerz/cordova/fingerprint"/>
- <source-file src="res/android/drawable/ic_fingerprint_error.xml" target-dir="res/drawable"/>
- <source-file src="res/android/drawable/ic_fingerprint_success.xml" target-dir="res/drawable"/>
- <resource-file src="res/android/drawable-hdpi/ic_fp_40px.png" target="res/drawable-hdpi/ic_fp_40px.png"/>
- <resource-file src="res/android/drawable-mdpi/ic_fp_40px.png" target="res/drawable-mdpi/ic_fp_40px.png"/>
- <resource-file src="res/android/drawable-nodpi/android_robot.png" target="res/drawable-nodpi/android_robot.png"/>
- <resource-file src="res/android/drawable-xhdpi/ic_fp_40px.png" target="res/drawable-xhdpi/ic_fp_40px.png"/>
- <resource-file src="res/android/drawable-xxhdpi/ic_fp_40px.png" target="res/drawable-xxhdpi/ic_fp_40px.png"/>
- <resource-file src="res/android/drawable-xxxhdpi/ic_fp_40px.png" target="res/drawable-xxxhdpi/ic_fp_40px.png"/>
- <source-file src="res/android/layout/fingerprint_dialog_container.xml" target-dir="res/layout"/>
- <source-file src="res/android/layout/fingerprint_dialog_content.xml" target-dir="res/layout"/>
- <source-file src="res/android/values/fpauth-colors.xml" target-dir="res/values"/>
- <source-file src="res/android/values/fpauth-strings.xml" target-dir="res/values"/>
- <source-file src="res/android/values-es/fpauth-strings.xml" target-dir="res/values-es"/>
- <source-file src="res/android/values-de/fpauth-strings.xml" target-dir="res/values-de"/>
- <source-file src="res/android/values-fr/fpauth-strings.xml" target-dir="res/values-fr"/>
- <source-file src="res/android/values-zh/fpauth-strings.xml" target-dir="res/values-zh"/>
- <source-file src="res/android/values-pt/fpauth-strings.xml" target-dir="res/values-pt"/>
- <source-file src="res/android/values-it/fpauth-strings.xml" target-dir="res/values-it"/>
- <source-file src="res/android/values-el/fpauth-strings.xml" target-dir="res/values-el"/>
- <source-file src="res/android/values-zh-rTW/fpauth-strings.xml" target-dir="res/values-zh-rTW"/>
- <source-file src="res/android/values-nl/fpauth-strings.xml" target-dir="res/values-nl"/>
- <source-file src="res/android/values-da/fpauth-strings.xml" target-dir="res/values-da"/>
+ <config-file target="AndroidManifest.xml" parent="/manifest/application">
+ <activity
+ android:name="de.niklasmerz.cordova.biometric.BiometricActivity"
+ android:theme="@style/TransparentTheme"
+ android:exported="true" />
+ </config-file>
+
+ <framework src="src/android/build.gradle" custom="true" type="gradleReference"/>
+ <resource-file src="src/android/res/biometric_activity.xml" target="res/layout/biometric_activity.xml" />
+ <resource-file src="src/android/res/styles.xml" target="res/values/biometric-styles.xml" />
+ <source-file src="src/android/PromptInfo.java" target-dir="src/de/niklasmerz/cordova/biometric"/>
+ <source-file src="src/android/BiometricActivity.java" target-dir="src/de/niklasmerz/cordova/biometric"/>
+ <source-file src="src/android/Fingerprint.java" target-dir="src/de/niklasmerz/cordova/biometric"/>
+ <source-file src="src/android/PluginError.java" target-dir="src/de/niklasmerz/cordova/biometric"/>
</platform>
+ <engines>
+ <engine name="cordova-android" version=">=8.0.0" />
+ </engines>
+
</plugin>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="40.0dp"
- android:height="40.0dp"
- android:viewportWidth="40.0"
- android:viewportHeight="40.0">
- <path
- android:pathData="M20.0,0.0C8.96,0.0 0.0,8.95 0.0,20.0s8.96,20.0 20.0,20.0c11.04,0.0 20.0,-8.95 20.0,-20.0S31.04,0.0 20.0,0.0z"
- android:fillColor="#F4511E"/>
- <path
- android:pathData="M21.33,29.33l-2.67,0.0l0.0,-2.67l2.67,0.0L21.33,29.33zM21.33,22.67l-2.67,0.0l0.0,-12.0l2.67,0.0L21.33,22.67z"
- android:fillColor="#FFFFFF"/>
-</vector>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="40.0dp"
- android:height="40.0dp"
- android:viewportWidth="40.0"
- android:viewportHeight="40.0">
- <path
- android:pathData="M20.0,20.0m-20.0,0.0a20.0,20.0 0.0,1.0 1.0,40.0 0.0a20.0,20.0 0.0,1.0 1.0,-40.0 0.0"
- android:fillColor="#009688"/>
- <path
- android:pathData="M11.2,21.41l1.63,-1.619999 4.17,4.169998 10.59,-10.589999 1.619999,1.63 -12.209999,12.209999z"
- android:fillColor="#FFFFFF"/>
-</vector>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <include layout="@layout/fingerprint_dialog_content" />
-
- </FrameLayout>
-
- <LinearLayout
- android:id="@+id/buttonPanel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingStart="12dp"
- android:paddingEnd="12dp"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:gravity="bottom"
- style="?android:attr/buttonBarStyle">
-
- <Space
- android:id="@+id/spacer"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:visibility="invisible" />
- <Button
- android:id="@+id/cancel_button"
- style="?android:attr/buttonBarNegativeButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <Button
- android:id="@+id/second_dialog_button"
- style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/fingerprint_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="8dp"
- android:paddingStart="24dp"
- android:paddingEnd="24dp"
- android:paddingTop="16dp">
-
- <TextView
- android:id="@+id/fingerprint_description"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:text="@string/fingerprint_description"
- android:textAppearance="@android:style/TextAppearance.Material.Subhead"
- android:textColor="?android:attr/textColorSecondary"/>
-
-
- <ImageView
- android:id="@+id/fingerprint_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@+id/fingerprint_description"
- android:layout_marginTop="20dp"
- android:src="@drawable/ic_fp_40px" />
-
- <TextView
- android:id="@+id/fingerprint_status"
- style="@android:style/TextAppearance.Material.Body1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBottom="@+id/fingerprint_icon"
- android:layout_alignTop="@+id/fingerprint_icon"
- android:layout_marginStart="16dp"
- android:layout_toEndOf="@+id/fingerprint_icon"
- android:gravity="center_vertical"
- android:text="@string/fingerprint_hint"
- android:textColor="@color/hint_color" />
-</RelativeLayout>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Annuller</string>
- <string name="fingerprint_use_backup">Brug backup</string>
- <string name="fingerprint_auth_dialog_title">Fingeraftryk Login</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Bekræft fingeraftryk for at fortsætte</string>
- <string name="fingerprint_hint">Rør sensor</string>
- <string name="fingerprint_not_recognized">Fingeraftryk ikke genkendt. Prøv igen.</string>
- <string name="fingerprint_success">Fingeraftryk godkendt</string>
- <string name="new_fingerprint_enrolled_description">Et nyt fingeraftryk blev tilføjet til denne enhed så din adgangskode er krævet.</string>
- <string name="secure_lock_screen_required">Sikring af skærmlås krævet!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Abbrechen</string>
- <string name="fingerprint_use_backup">Passwort</string>
- <string name="fingerprint_auth_dialog_title">Authentifizierung</string>
- <string name="fingerprint_ok">OK</string>
- <string name="fingerprint_description">Fingerabdruck bestätigen</string>
- <string name="fingerprint_hint">Fingerabdrucksensor</string>
- <string name="fingerprint_not_recognized">Fingerabdruck nicht erkannt. Versuchen Sie es erneut</string>
- <string name="fingerprint_success">Authentifiziert</string>
- <string name="new_fingerprint_enrolled_description">Ein neuer Fingerabdruck wurde gespeichert. Bitte geben Sie ihr Passwort ein.</string>
- <string name="secure_lock_screen_required">Passwortgeschützter Sperrbildschirm benötigt</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Ακύρωση</string>
- <string name="fingerprint_use_backup">Χρήση αρχείου</string>
- <string name="fingerprint_auth_dialog_title">Ελεγχος αποτυπώματος</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Επιβεβαίωση αποτυπώματος</string>
- <string name="fingerprint_hint">Αιθηστήρας αφής</string>
- <string name="fingerprint_not_recognized">Σφάλμα. Προσπαθήστε ξανά</string>
- <string name="fingerprint_success">Σωστό αποτύπωμα</string>
- <string name="new_fingerprint_enrolled_description">Νεο αποτύπωμα προστέθηκε , απαιτείται ο κωδικός σας.</string>
- <string name="secure_lock_screen_required">Απαιτείται κλειδωμα οθόνης</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Cancelar</string>
- <string name="fingerprint_use_backup">El Respaldo</string>
- <string name="fingerprint_auth_dialog_title">Autenticación de Huellas Digitales</string>
- <string name="fingerprint_ok">De Acuerdo</string>
- <string name="fingerprint_description">Confirmar la huella digital para continuar</string>
- <string name="fingerprint_hint">Sensor tactil</string>
- <string name="fingerprint_not_recognized">No se reconoce la huella digital. Inténtalo de nuevo.</string>
- <string name="fingerprint_success">Reconocido de huella dactilar</string>
- <string name="new_fingerprint_enrolled_description">Una nueva huella digital fue agregada a este dispositivo, por lo que se requiere la contraseña.</string>
- <string name="secure_lock_screen_required">¡Requiere pantalla de bloqueo seguro!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Annuler</string>
- <string name="fingerprint_use_backup">Utiliser la sauvegarde</string>
- <string name="fingerprint_auth_dialog_title">Authentification par empreinte digitale</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Confirmer l\'empreinte pour continuer</string>
- <string name="fingerprint_hint">Toucher le capteur</string>
- <string name="fingerprint_not_recognized">Empreinte non reconnue. Essayer à nouveau.</string>
- <string name="fingerprint_success">Empreinte reconnue</string>
- <string name="new_fingerprint_enrolled_description">Une nouvelle empreinte digitale a été ajoutée à ce dispositif, de sorte que votre mot de passe est nécessaire.</string>
- <string name="secure_lock_screen_required">Écran de verrouillage sécurisé nécessaire!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Cancella</string>
- <string name="fingerprint_use_backup">Usa backup</string>
- <string name="fingerprint_auth_dialog_title">Autenticazione impronta digitale</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Conferma l\'impronta digitale per continuare</string>
- <string name="fingerprint_hint">Sensore Touch</string>
- <string name="fingerprint_not_recognized">Impronta digitale non riconosciuta. Riprova.</string>
- <string name="fingerprint_success">Impronta digitale riconosciuta</string>
- <string name="new_fingerprint_enrolled_description">Una nuova impronta è stata aggiunta a questo dispositivo, quindi è necessaria la tua password</string>
- <string name="secure_lock_screen_required">Blocco schermo richiesto!</string>
-</resources>
+++ /dev/null
-<resources>
- <string name="fingerprint_cancel">Annuleer</string>
- <string name="fingerprint_use_backup">Back-up gebruiken</string>
- <string name="fingerprint_auth_dialog_title">Authenticatie met vingerafdruk</string>
- <string name="fingerprint_ok">OK</string>
- <string name="fingerprint_description">Vingerafdruk bevestigen om verder te gaan</string>
- <string name="fingerprint_hint">Aanraaksensor</string>
- <string name="fingerprint_not_recognized">Vingerafdruk niet herkend.Opnieuw proberen.</string>
- <string name="fingerprint_success">Vingerafdruk herkend</string>
- <string name="new_fingerprint_enrolled_description">Er werd een nieuwe vingerafdruk aan dit apparaat toegevoegd, waardoor uw wachtwoord is vereist.</string>
- <string name="secure_lock_screen_required">Beveiligd vergrendelingsscherm vereist!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">Cancelar</string>
- <string name="fingerprint_use_backup">Use o backup</string>
- <string name="fingerprint_auth_dialog_title">Autenticação de impressão digital</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Confirme a impressão digital para continuar</string>
- <string name="fingerprint_hint">Sensor de toque</string>
- <string name="fingerprint_not_recognized">impressão digital não reconhecida. Tente novamente.</string>
- <string name="fingerprint_success">impressão digital reconhecida</string>
- <string name="new_fingerprint_enrolled_description">Uma nova impressão digital foi adicionada a este dispositivo, é necessário o seu código</string>
- <string name="secure_lock_screen_required">É necessário um ecrã de bloqueio seguro!</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">取消</string>
- <string name="fingerprint_use_backup">使用手勢密碼</string>
- <string name="fingerprint_auth_dialog_title">指紋識別</string>
- <string name="fingerprint_ok">確認</string><string name="fingerprint_description">指紋識別</string>
- <string name="fingerprint_hint">請觸摸指紋識別傳感器</string>
- <string name="fingerprint_not_recognized">指紋無法識別,請再試一次</string>
- <string name="fingerprint_success">指紋識別成功</string>
- <string name="new_fingerprint_enrolled_description">添加一個新的指紋,需要設置密碼</string>
- <string name="secure_lock_screen_required">需要安全鎖屏</string>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="fingerprint_cancel">取消</string>
- <string name="fingerprint_use_backup">使用手势密码</string>
- <string name="fingerprint_auth_dialog_title">指纹识别</string>
- <string name="fingerprint_ok">确认</string><string name="fingerprint_description">指纹识别</string>
- <string name="fingerprint_hint">请触摸指纹识传感器</string>
- <string name="fingerprint_not_recognized">指纹无法识别,请再试一次</string>
- <string name="fingerprint_success">指纹识别成功</string>
- <string name="new_fingerprint_enrolled_description">添加一个新的指纹,需要设置密码</string>
- <string name="secure_lock_screen_required">需要安全锁屏</string>
-</resources>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <color name="warning_color">#f4511e</color>
- <color name="hint_color">#42000000</color>
- <color name="success_color">#009688</color>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<resources>
- <string name="fingerprint_cancel">Cancel</string>
- <string name="fingerprint_use_backup">Use backup</string>
- <string name="fingerprint_auth_dialog_title">Fingerprint Authentication</string>
- <string name="fingerprint_ok">Ok</string>
- <string name="fingerprint_description">Confirm fingerprint to continue</string>
- <string name="fingerprint_hint">Touch sensor</string>
- <string name="fingerprint_not_recognized">Fingerprint not recognized. Try again.</string>
- <string name="fingerprint_success">Fingerprint recognized</string>
- <string name="new_fingerprint_enrolled_description">A new fingerprint was added to this device, so your password is required.</string>
- <string name="secure_lock_screen_required">Secure lock screen required!</string>
-</resources>
--- /dev/null
+#Sat Nov 16 11:08:08 CET 2019
+gradle.version=6.0-20191016123526+0000
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>android</name>
+ <comment>Project android created by Buildship.</comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.buildship.core.gradleprojectbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.buildship.core.gradleprojectnature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+arguments=
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.0-20191016123526+0000))
+connection.project.dir=
+eclipse.preferences.version=1
+gradle.user.home=
+java.home=
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=true
+show.console.view=true
+show.executions.view=true
--- /dev/null
+package de.niklasmerz.cordova.biometric;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AppCompatActivity;
+
+import com.exxbrain.android.biometric.BiometricPrompt;
+
+import java.util.concurrent.Executor;
+
+public class BiometricActivity extends AppCompatActivity {
+
+ private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 2;
+ private PromptInfo mPromptInfo;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setTitle(null);
+ int layout = getResources()
+ .getIdentifier("biometric_activity", "layout", getPackageName());
+ setContentView(layout);
+
+ if (savedInstanceState != null) {
+ return;
+ }
+
+ mPromptInfo = new PromptInfo.Builder(getIntent().getExtras()).build();
+ authenticate();
+
+ }
+
+ private void authenticate() {
+ final Handler handler = new Handler(Looper.getMainLooper());
+ Executor executor = handler::post;
+
+ BiometricPrompt biometricPrompt =
+ new BiometricPrompt(this, executor, mAuthenticationCallback);
+
+ BiometricPrompt.PromptInfo.Builder promptInfoBuilder = new BiometricPrompt.PromptInfo.Builder()
+ .setTitle(mPromptInfo.getTitle())
+ .setSubtitle(mPromptInfo.getSubtitle())
+ .setDescription(mPromptInfo.getDescription());
+
+ if (mPromptInfo.isDeviceCredentialAllowed()
+ && Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ promptInfoBuilder.setDeviceCredentialAllowed(true);
+ } else {
+ promptInfoBuilder.setNegativeButtonText(mPromptInfo.getCancelButtonTitle());
+ }
+
+ biometricPrompt.authenticate(promptInfoBuilder.build());
+ }
+
+ private BiometricPrompt.AuthenticationCallback mAuthenticationCallback =
+ new BiometricPrompt.AuthenticationCallback() {
+
+ @Override
+ public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
+ super.onAuthenticationError(errorCode, errString);
+ onError(errorCode, errString);
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
+ super.onAuthenticationSucceeded(result);
+ finishWithSuccess();
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+ super.onAuthenticationFailed();
+ }
+ };
+
+
+ // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ private void showAuthenticationScreen() {
+ KeyguardManager keyguardManager = ContextCompat
+ .getSystemService(this, KeyguardManager.class);
+ if (keyguardManager == null
+ || android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
+ return;
+ }
+ if (keyguardManager.isKeyguardSecure()) {
+ Intent intent = keyguardManager
+ .createConfirmDeviceCredentialIntent(mPromptInfo.getTitle(), mPromptInfo.getDescription());
+ this.startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
+ } else {
+ // Show a message that the user hasn't set up a lock screen.
+ finishWithError(PluginError.BIOMETRIC_SCREEN_GUARD_UNSECURED);
+ }
+ }
+
+ // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
+ if (resultCode == Activity.RESULT_OK) {
+ finishWithSuccess();
+ } else {
+ finishWithError(PluginError.BIOMETRIC_PIN_OR_PATTERN_DISMISSED);
+ }
+ }
+ }
+
+ private void onError(int errorCode, @NonNull CharSequence errString) {
+
+ switch (errorCode)
+ {
+ case BiometricPrompt.ERROR_USER_CANCELED:
+ case BiometricPrompt.ERROR_CANCELED:
+ finishWithError(PluginError.BIOMETRIC_DISMISSED);
+ return;
+ case BiometricPrompt.ERROR_NEGATIVE_BUTTON:
+ // TODO: remove after fix https://issuetracker.google.com/issues/142740104
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P && mPromptInfo.isDeviceCredentialAllowed()) {
+ showAuthenticationScreen();
+ return;
+ }
+ finishWithError(PluginError.BIOMETRIC_DISMISSED);
+ break;
+ case BiometricPrompt.ERROR_LOCKOUT:
+ finishWithError(PluginError.BIOMETRIC_LOCKED_OUT.getValue(), errString.toString());
+ break;
+ case BiometricPrompt.ERROR_LOCKOUT_PERMANENT:
+ finishWithError(PluginError.BIOMETRIC_LOCKED_OUT_PERMANENT.getValue(), errString.toString());
+ break;
+ default:
+ finishWithError(errorCode, errString.toString());
+ }
+ }
+
+ private void finishWithSuccess() {
+ setResult(RESULT_OK);
+ finish();
+ }
+
+ private void finishWithError(PluginError error) {
+ finishWithError(error.getValue(), error.getMessage());
+ }
+
+ private void finishWithError(int code, String message) {
+ Intent data = new Intent();
+ data.putExtra("code", code);
+ data.putExtra("message", message);
+ setResult(RESULT_CANCELED, data);
+ finish();
+ }
+}
-/*
- * Copyright (C) https://github.com/mjwheatley/cordova-plugin-android-fingerprint-auth
- * Modifications copyright (C) 2016 Niklas Merz
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
+package de.niklasmerz.cordova.biometric;
-package de.niklasmerz.cordova.fingerprint;
-
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaInterface;
-
-import android.annotation.TargetApi;
-import android.app.FragmentTransaction;
-import android.app.KeyguardManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.hardware.fingerprint.FingerprintManager;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Build;
import android.os.Bundle;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyPermanentlyInvalidatedException;
-import android.security.keystore.KeyProperties;
-import android.util.Base64;
-import android.util.DisplayMetrics;
import android.util.Log;
+import com.exxbrain.android.biometric.BiometricManager;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import java.io.IOException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.util.Locale;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.KeyGenerator;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
-
-@TargetApi(23)
public class Fingerprint extends CordovaPlugin {
- public static final String TAG = "Fingerprint";
- public static String packageName;
-
- private static final String DIALOG_FRAGMENT_TAG = "FpAuthDialog";
- private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
+ private static final String TAG = "Fingerprint";
+ private CallbackContext mCallbackContext = null;
- KeyguardManager mKeyguardManager;
- FingerprintAuthenticationDialogFragment mFragment;
- public static KeyStore mKeyStore;
- public static KeyGenerator mKeyGenerator;
- public static Cipher mCipher;
- private FingerprintManager mFingerPrintManager;
-
- public static CallbackContext mCallbackContext;
- public static PluginResult mPluginResult;
-
- /**
- * Alias for our key in the Android Key Store
- */
- private static String mClientId;
- /**
- * Used to encrypt token
- */
- private static String mClientSecret;
-
- /**
- * Options
- */
- private static boolean mDisableBackup = false;
-
- /**
- * Constructor.
- */
- public Fingerprint() {
- }
-
- /**
- * Sets the context of the Command. This can then be used to do things like
- * get file paths associated with the Activity.
- *
- * @param cordova The context of the main Activity.
- * @param webView The CordovaWebView Cordova is running in.
- */
+ private static final int REQUEST_CODE_BIOMETRIC = 1;
+ private PromptInfo.Builder mPromptInfoBuilder;
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
Log.v(TAG, "Init Fingerprint");
- packageName = cordova.getActivity().getApplicationContext().getPackageName();
- mPluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
-
- if (android.os.Build.VERSION.SDK_INT < 23) {
- return;
- }
-
- mKeyguardManager = cordova.getActivity().getSystemService(KeyguardManager.class);
- mFingerPrintManager = cordova.getActivity().getApplicationContext()
- .getSystemService(FingerprintManager.class);
-
- try {
- mKeyGenerator = KeyGenerator.getInstance(
- KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
- mKeyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
-
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
- } catch (NoSuchProviderException e) {
- throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
- } catch (KeyStoreException e) {
- throw new RuntimeException("Failed to get an instance of KeyStore", e);
- }
-
- try {
- mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
- + KeyProperties.BLOCK_MODE_CBC + "/"
- + KeyProperties.ENCRYPTION_PADDING_PKCS7);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("Failed to get an instance of Cipher", e);
- } catch (NoSuchPaddingException e) {
- throw new RuntimeException("Failed to get an instance of Cipher", e);
- }
+ mPromptInfoBuilder = new PromptInfo.Builder(cordova.getActivity());
}
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackContext The callback id used when calling back into JavaScript.
- * @return A PluginResult object with a status and message.
- */
- public boolean execute(final String action,
- JSONArray args,
- CallbackContext callbackContext) throws JSONException {
- mCallbackContext = callbackContext;
- Log.v(TAG, "Fingerprint action: " + action);
- if (android.os.Build.VERSION.SDK_INT < 23) {
- Log.e(TAG, "minimum SDK version 23 required");
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.error("minimum SDK version 23 required");
- mCallbackContext.sendPluginResult(mPluginResult);
- return true;
- }
+ public boolean execute(final String action, JSONArray args, CallbackContext callbackContext) {
- final JSONObject arg_object = args.getJSONObject(0);
+ this.mCallbackContext = callbackContext;
+ Log.v(TAG, "Fingerprint action: " + action);
if (action.equals("authenticate")) {
- if (!arg_object.has("clientId") || !arg_object.has("clientSecret")) {
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.error("Missing required parameters");
- mCallbackContext.sendPluginResult(mPluginResult);
- return true;
- }
- mClientId = arg_object.getString("clientId");
- mClientSecret = arg_object.getString("clientSecret");
- if (arg_object.has("disableBackup")) {
- mDisableBackup = arg_object.getBoolean("disableBackup");
- }
- // Set language
- Resources res = cordova.getActivity().getResources();
- // Change locale settings in the app.
- DisplayMetrics dm = res.getDisplayMetrics();
- Configuration conf = res.getConfiguration();
- //Do not change locale
- res.updateConfiguration(conf, dm);
-
- if (isFingerprintAuthAvailable()) {
- SecretKey key = getSecretKey();
- boolean isCipherInit = true;
- if (key == null) {
- if (createKey()) {
- key = getSecretKey();
- }
- }
- if (key != null && !initCipher()) {
- isCipherInit = false;
- }
- if (key != null) {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- // Set up the crypto object for later. The object will be authenticated by use
- // of the fingerprint.
- mFragment = new FingerprintAuthenticationDialogFragment();
- Bundle bundle = new Bundle();
- bundle.putBoolean("disableBackup", mDisableBackup);
- mFragment.setArguments(bundle);
-
- if (initCipher()) {
- mFragment.setCancelable(false);
- // Show the fingerprint dialog. The user has the option to use the fingerprint with
- // crypto, or you can fall back to using a server-side verified password.
- mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
- FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction();
- transaction.add(mFragment, DIALOG_FRAGMENT_TAG);
- transaction.commitAllowingStateLoss();
- } else {
- if (!mDisableBackup) {
- // This happens if the lock screen has been disabled or or a fingerprint got
- // enrolled. Thus show the dialog to authenticate with their password
- mFragment.setCryptoObject(new FingerprintManager
- .CryptoObject(mCipher));
- mFragment.setStage(FingerprintAuthenticationDialogFragment
- .Stage.NEW_FINGERPRINT_ENROLLED);
- FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction();
- transaction.add(mFragment, DIALOG_FRAGMENT_TAG);
- transaction.commitAllowingStateLoss();
- } else {
- mCallbackContext.error("Failed to init Cipher and backup disabled.");
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.sendPluginResult(mPluginResult);
- }
- }
- }
- });
- mPluginResult.setKeepCallback(true);
- } else {
- mCallbackContext.sendPluginResult(mPluginResult);
- }
-
- } else {
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- mCallbackContext.error("Fingerprint authentication not available");
- mCallbackContext.sendPluginResult(mPluginResult);
- }
+ executeAuthenticate(args);
return true;
- } else if (action.equals("isAvailable")) {
- if(isFingerprintAuthAvailable() && mFingerPrintManager.isHardwareDetected() && mFingerPrintManager.hasEnrolledFingerprints()){
- mPluginResult = new PluginResult(PluginResult.Status.OK, "finger");
- mCallbackContext.success("finger");
- }else{
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- if (mFingerPrintManager.isHardwareDetected() && !mFingerPrintManager.hasEnrolledFingerprints()) {
- mCallbackContext.error("Fingerprint authentication not ready");
- } else {
- mCallbackContext.error("Fingerprint authentication not available");
- }
- }
- mCallbackContext.sendPluginResult(mPluginResult);
+ } else if (action.equals("isAvailable")){
+ executeIsAvailable();
return true;
}
+
return false;
}
- private boolean isFingerprintAuthAvailable() {
- return mFingerPrintManager.isHardwareDetected()
- && mFingerPrintManager.hasEnrolledFingerprints();
+ private void executeIsAvailable() {
+ PluginError error = canAuthenticate();
+ if (error != null) {
+ sendError(error);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
+ sendSuccess("biometric");
+ } else {
+ sendSuccess("finger");
+ }
}
- /**
- * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()}
- * method.
- *
- * @return {@code true} if initialization is successful, {@code false} if the lock screen has
- * been disabled or reset after the key was generated, or if a fingerprint got enrolled after
- * the key was generated.
- */
- private static boolean initCipher() {
- boolean initCipher = false;
- String errorMessage = "";
- String initCipherExceptionErrorPrefix = "Failed to init Cipher: ";
- try {
- SecretKey key = getSecretKey();
- mCipher.init(Cipher.ENCRYPT_MODE, key);
- initCipher = true;
- } catch (InvalidKeyException e) {
- errorMessage = initCipherExceptionErrorPrefix + "InvalidKeyException: " + e.toString();
-
- }
- if (!initCipher) {
- Log.e(TAG, errorMessage);
- createKey();
+ private void executeAuthenticate(JSONArray args) {
+ PluginError error = canAuthenticate();
+ if (error != null) {
+ sendError(error);
+ return;
}
- return initCipher;
+ cordova.getActivity().runOnUiThread(() -> {
+ mPromptInfoBuilder.parseArgs(args);
+ Intent intent = new Intent(cordova.getActivity().getApplicationContext(), BiometricActivity.class);
+ intent.putExtras(mPromptInfoBuilder.build().getBundle());
+ this.cordova.startActivityForResult(this, intent, REQUEST_CODE_BIOMETRIC);
+ });
+ PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
+ pluginResult.setKeepCallback(true);
+ this.mCallbackContext.sendPluginResult(pluginResult);
}
- private static SecretKey getSecretKey() {
- String errorMessage = "";
- String getSecretKeyExceptionErrorPrefix = "Failed to get SecretKey from KeyStore: ";
- SecretKey key = null;
- try {
- mKeyStore.load(null);
- key = (SecretKey) mKeyStore.getKey(mClientId, null);
- } catch (KeyStoreException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "KeyStoreException: " + e.toString();;
- } catch (CertificateException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "CertificateException: " + e.toString();;
- } catch (UnrecoverableKeyException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "UnrecoverableKeyException: " + e.toString();;
- } catch (IOException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "IOException: " + e.toString();;
- } catch (NoSuchAlgorithmException e) {
- errorMessage = getSecretKeyExceptionErrorPrefix
- + "NoSuchAlgorithmException: " + e.toString();;
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ super.onActivityResult(requestCode, resultCode, intent);
+ if (requestCode != REQUEST_CODE_BIOMETRIC) {
+ return;
}
- if (key == null) {
- Log.e(TAG, errorMessage);
+ if (resultCode == Activity.RESULT_OK) {
+ sendSuccess("biometric_success");
+ } else if (intent != null) {
+ Bundle extras = intent.getExtras();
+ sendError(extras.getInt("code"), extras.getString("message"));
+ } else {
+ sendError(PluginError.BIOMETRIC_DISMISSED);
}
- return key;
}
- /**
- * Creates a symmetric key in the Android Key Store which can only be used after the user has
- * authenticated with fingerprint.
- */
- public static boolean createKey() {
- String errorMessage = "";
- String createKeyExceptionErrorPrefix = "Failed to create key: ";
- boolean isKeyCreated = false;
- // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
- // for your flow. Use of keys is necessary if you need to know if the set of
- // enrolled fingerprints has changed.
- try {
- mKeyStore.load(null);
- // Set the alias of the entry in Android KeyStore where the key will appear
- // and the constrains (purposes) in the constructor of the Builder
- mKeyGenerator.init(new KeyGenParameterSpec.Builder(mClientId,
- KeyProperties.PURPOSE_ENCRYPT |
- KeyProperties.PURPOSE_DECRYPT)
- .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
- // Require the user to authenticate with a fingerprint to authorize every use
- // of the key
- .setUserAuthenticationRequired(true)
- .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
- .build());
- mKeyGenerator.generateKey();
- isKeyCreated = true;
- } catch (NoSuchAlgorithmException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "NoSuchAlgorithmException: " + e.toString();;
- } catch (InvalidAlgorithmParameterException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "InvalidAlgorithmParameterException: " + e.toString();;
- } catch (CertificateException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "CertificateException: " + e.toString();;
- } catch (IOException e) {
- errorMessage = createKeyExceptionErrorPrefix
- + "IOException: " + e.toString();;
- }
- if (!isKeyCreated) {
- Log.e(TAG, errorMessage);
- setPluginResultError(errorMessage);
+ private PluginError canAuthenticate() {
+ int error = BiometricManager.from(cordova.getContext()).canAuthenticate();
+ switch (error) {
+ case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
+ case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
+ return PluginError.BIOMETRIC_HARDWARE_NOT_SUPPORTED;
+ case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
+ return PluginError.BIOMETRIC_NOT_ENROLLED;
+ default:
+ return null;
}
- return isKeyCreated;
}
- public static void onAuthenticated(boolean withFingerprint) {
+ private void sendError(int code, String message) {
JSONObject resultJson = new JSONObject();
- String errorMessage = "";
- boolean createdResultJson = false;
try {
+ resultJson.put("code", code);
+ resultJson.put("message", message);
- if (withFingerprint) {
- // If the user has authenticated with fingerprint, verify that using cryptography and
- // then return the encrypted token
- byte[] encrypted = tryEncrypt();
- resultJson.put("withFingerprint", Base64.encodeToString(encrypted, 0 /* flags */));
- } else {
- // Authentication happened with backup password.
- resultJson.put("withPassword", true);
-
- // if failed to init cipher because of InvalidKeyException, create new key
- if (!initCipher()) {
- createKey();
- }
- }
- createdResultJson = true;
- } catch (BadPaddingException e) {
- errorMessage = "Failed to encrypt the data with the generated key:" +
- " BadPaddingException: " + e.getMessage();
- Log.e(TAG, errorMessage);
- } catch (IllegalBlockSizeException e) {
- errorMessage = "Failed to encrypt the data with the generated key: " +
- "IllegalBlockSizeException: " + e.getMessage();
- Log.e(TAG, errorMessage);
+ PluginResult result = new PluginResult(PluginResult.Status.ERROR, resultJson);
+ result.setKeepCallback(true);
+ cordova.getActivity().runOnUiThread(() ->
+ Fingerprint.this.mCallbackContext.sendPluginResult(result));
} catch (JSONException e) {
- errorMessage = "Failed to set resultJson key value pair: " + e.getMessage();
- Log.e(TAG, errorMessage);
- }
-
- if (createdResultJson) {
- mCallbackContext.success(resultJson);
- mPluginResult = new PluginResult(PluginResult.Status.OK);
- } else {
- mCallbackContext.error(errorMessage);
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+ Log.e(TAG, e.getMessage(), e);
}
- mCallbackContext.sendPluginResult(mPluginResult);
}
- public static void onCancelled() {
- mCallbackContext.error("Cancelled");
+ private void sendError(PluginError error) {
+ sendError(error.getValue(), error.getMessage());
}
- /**
- * Tries to encrypt some data with the generated key in {@link #createKey} which is
- * only works if the user has just authenticated via fingerprint.
- */
- private static byte[] tryEncrypt() throws BadPaddingException, IllegalBlockSizeException {
- return mCipher.doFinal(mClientSecret.getBytes());
- }
-
- public static boolean setPluginResultError(String errorMessage) {
- mCallbackContext.error(errorMessage);
- mPluginResult = new PluginResult(PluginResult.Status.ERROR);
- return false;
+ private void sendSuccess(String message) {
+ Log.e(TAG, message);
+ cordova.getActivity().runOnUiThread(() ->
+ this.mCallbackContext.success(message));
}
-}
\ No newline at end of file
+}
+++ /dev/null
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * Modifications copyright (C) 2016 Niklas Merz
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package de.niklasmerz.cordova.fingerprint;
-
-import android.app.DialogFragment;
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.hardware.fingerprint.FingerprintManager;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-/**
- * A dialog which uses fingerprint APIs to authenticate the user, and falls back to password
- * authentication if fingerprint is not available.
- */
-public class FingerprintAuthenticationDialogFragment extends DialogFragment
- implements FingerprintUiHelper.Callback {
-
- private static final String TAG = "FingerprintAuthDialog";
- private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
-
- private Button mCancelButton;
- private Button mSecondDialogButton;
- private View mFingerprintContent;
-
- private Stage mStage = Stage.FINGERPRINT;
-
- private KeyguardManager mKeyguardManager;
- private FingerprintManager.CryptoObject mCryptoObject;
- private FingerprintUiHelper mFingerprintUiHelper;
- FingerprintUiHelper.FingerprintUiHelperBuilder mFingerprintUiHelperBuilder;
-
- boolean disableBackup;
-
- public FingerprintAuthenticationDialogFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Do not create a new Fragment when the Activity is re-created such as orientation changes.
- setRetainInstance(true);
- setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
-
- mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
- mFingerprintUiHelperBuilder = new FingerprintUiHelper.FingerprintUiHelperBuilder(
- getContext(), getContext().getSystemService(FingerprintManager.class));
-
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- Bundle args = getArguments();
- disableBackup = args.getBoolean("disableBackup");
- Log.d(TAG, "disableBackup: " + disableBackup);
-
- int fingerprint_auth_dialog_title_id = getResources()
- .getIdentifier("fingerprint_auth_dialog_title", "string",
- Fingerprint.packageName);
- getDialog().setTitle(getString(fingerprint_auth_dialog_title_id));
- int fingerprint_dialog_container_id = getResources()
- .getIdentifier("fingerprint_dialog_container", "layout",
- Fingerprint.packageName);
- View v = inflater.inflate(fingerprint_dialog_container_id, container, false);
- int cancel_button_id = getResources()
- .getIdentifier("cancel_button", "id", Fingerprint.packageName);
- mCancelButton = (Button) v.findViewById(cancel_button_id);
- mCancelButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Fingerprint.onCancelled();
- dismissAllowingStateLoss();
- }
- });
-
- int second_dialog_button_id = getResources()
- .getIdentifier("second_dialog_button", "id", Fingerprint.packageName);
- mSecondDialogButton = (Button) v.findViewById(second_dialog_button_id);
- if (disableBackup) {
- mSecondDialogButton.setVisibility(View.GONE);
- }
- mSecondDialogButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- goToBackup();
- }
- });
- int fingerprint_container_id = getResources()
- .getIdentifier("fingerprint_container", "id", Fingerprint.packageName);
- mFingerprintContent = v.findViewById(fingerprint_container_id);
-
- int new_fingerprint_enrolled_description_id = getResources()
- .getIdentifier("new_fingerprint_enrolled_description", "id",
- Fingerprint.packageName);
-
- int fingerprint_icon_id = getResources()
- .getIdentifier("fingerprint_icon", "id", Fingerprint.packageName);
- int fingerprint_status_id = getResources()
- .getIdentifier("fingerprint_status", "id", Fingerprint.packageName);
- mFingerprintUiHelper = mFingerprintUiHelperBuilder.build(
- (ImageView) v.findViewById(fingerprint_icon_id),
- (TextView) v.findViewById(fingerprint_status_id), this);
- updateStage();
-
- // If fingerprint authentication is not available, switch immediately to the backup
- // (password) screen.
- if (!mFingerprintUiHelper.isFingerprintAuthAvailable()) {
- goToBackup();
- }
- return v;
- }
-
-
- @Override
- public void onResume() {
- super.onResume();
- if (mStage == Stage.FINGERPRINT) {
- mFingerprintUiHelper.startListening(mCryptoObject);
- }
- }
-
- public void setStage(Stage stage) {
- mStage = stage;
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mFingerprintUiHelper.stopListening();
- }
-
- /**
- * Sets the crypto object to be passed in when authenticating with fingerprint.
- */
- public void setCryptoObject(FingerprintManager.CryptoObject cryptoObject) {
- mCryptoObject = cryptoObject;
- }
-
- /**
- * Switches to backup (password) screen. This either can happen when fingerprint is not
- * available or the user chooses to use the password authentication method by pressing the
- * button. This can also happen when the user had too many fingerprint attempts.
- */
- private void goToBackup() {
- if(disableBackup)
- {
- Fingerprint.onCancelled();
- dismissAllowingStateLoss();
- }
- else{
- mStage = Stage.BACKUP;
- updateStage();
- }
- }
-
- private void updateStage() {
- int cancel_id = getResources()
- .getIdentifier("fingerprint_cancel", "string", Fingerprint.packageName);
- switch (mStage) {
- case FINGERPRINT:
- mCancelButton.setText(cancel_id);
- int use_backup_id = getResources()
- .getIdentifier("fingerprint_use_backup", "string", Fingerprint.packageName);
- mSecondDialogButton.setText(use_backup_id);
- mFingerprintContent.setVisibility(View.VISIBLE);
- break;
- case NEW_FINGERPRINT_ENROLLED:
- // Intentional fall through
- case BACKUP:
- if (mStage == Stage.NEW_FINGERPRINT_ENROLLED) {
-
- }
- if (!mKeyguardManager.isKeyguardSecure()) {
- // Show a message that the user hasn't set up a lock screen.
- int secure_lock_screen_required_id = getResources()
- .getIdentifier("secure_lock_screen_required", "string",
- Fingerprint.packageName);
- Toast.makeText(getContext(),
- getString(secure_lock_screen_required_id),
- Toast.LENGTH_LONG).show();
- return;
- }
- showAuthenticationScreen();
- break;
- }
- }
-
- private void showAuthenticationScreen() {
- // Create the Confirm Credentials screen. You can customize the title and description. Or
- // we will provide a generic one for you if you leave it null
- Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
- if (intent != null) {
- startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
- // Challenge completed, proceed with using cipher
- if (resultCode == getActivity().RESULT_OK) {
- Fingerprint.onAuthenticated(false /* used backup */);
- } else {
- // The user canceled or didn’t complete the lock screen
- // operation. Go to error/cancellation flow.
- Fingerprint.onCancelled();
- }
- dismissAllowingStateLoss();
- }
- }
-
- @Override
- public void onAuthenticated() {
- // Callback from FingerprintUiHelper. Let the activity know that authentication was
- // successful.
- Fingerprint.onAuthenticated(true /* withFingerprint */);
- dismissAllowingStateLoss();
- }
-
- @Override
- public void onError() {
- if(this.getActivity() != null)
- goToBackup();
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- Fingerprint.onCancelled();
- }
-
- /**
- * Enumeration to indicate which authentication method the user is trying to authenticate with.
- */
- public enum Stage {
- FINGERPRINT,
- NEW_FINGERPRINT_ENROLLED,
- BACKUP
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * Modifications copyright (C) 2016 Niklas Merz
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package de.niklasmerz.cordova.fingerprint;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.hardware.fingerprint.FingerprintManager;
-import android.os.CancellationSignal;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-
-/**
- * Small helper class to manage text/icon around fingerprint authentication UI.
- */
-@TargetApi(23)
-public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
-
- static final long ERROR_TIMEOUT_MILLIS = 1600;
- static final long SUCCESS_DELAY_MILLIS = 1300;
-
- private final Context mContext;
- private final FingerprintManager mFingerprintManager;
- private final ImageView mIcon;
- private final TextView mErrorTextView;
- private final Callback mCallback;
- private CancellationSignal mCancellationSignal;
-
- boolean mSelfCancelled;
-
- /**
- * Builder class for {@link FingerprintUiHelper} in which injected fields from Dagger
- * holds its fields and takes other arguments in the {@link #build} method.
- */
- public static class FingerprintUiHelperBuilder {
- private final FingerprintManager mFingerPrintManager;
- private final Context mContext;
-
- public FingerprintUiHelperBuilder(Context context, FingerprintManager fingerprintManager) {
- mFingerPrintManager = fingerprintManager;
- mContext = context;
- }
-
- public FingerprintUiHelper build(ImageView icon, TextView errorTextView, Callback callback) {
- return new FingerprintUiHelper(mContext, mFingerPrintManager, icon, errorTextView,
- callback);
- }
- }
-
- /**
- * Constructor for {@link FingerprintUiHelper}. This method is expected to be called from
- * only the {@link FingerprintUiHelperBuilder} class.
- */
- private FingerprintUiHelper(Context context, FingerprintManager fingerprintManager,
- ImageView icon, TextView errorTextView, Callback callback) {
- mFingerprintManager = fingerprintManager;
- mIcon = icon;
- mErrorTextView = errorTextView;
- mCallback = callback;
- mContext = context;
- }
-
- public boolean isFingerprintAuthAvailable() {
- return mFingerprintManager.isHardwareDetected()
- && mFingerprintManager.hasEnrolledFingerprints();
- }
-
- public void startListening(FingerprintManager.CryptoObject cryptoObject) {
- if (!isFingerprintAuthAvailable()) {
- return;
- }
- mCancellationSignal = new CancellationSignal();
- mSelfCancelled = false;
- mFingerprintManager
- .authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
-
- int ic_fp_40px_id = mContext.getResources()
- .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fp_40px_id);
- }
-
- public void stopListening() {
- if (mCancellationSignal != null) {
- mSelfCancelled = true;
- mCancellationSignal.cancel();
- mCancellationSignal = null;
- }
- }
-
- @Override
- public void onAuthenticationError(int errMsgId, CharSequence errString) {
- if (!mSelfCancelled) {
- showError(errString);
- mIcon.postDelayed(new Runnable() {
- @Override
- public void run() {
- mCallback.onError();
- }
- }, ERROR_TIMEOUT_MILLIS);
- }
- }
-
- @Override
- public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
- showError(helpString);
- }
-
- @Override
- public void onAuthenticationFailed() {
- int fingerprint_not_recognized_id = mContext.getResources()
- .getIdentifier("fingerprint_not_recognized", "string", Fingerprint.packageName);
- showError(mIcon.getResources().getString(
- fingerprint_not_recognized_id));
- }
-
- @Override
- public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
- mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
- int ic_fingerprint_success_id = mContext.getResources()
- .getIdentifier("ic_fingerprint_success", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fingerprint_success_id);
- int success_color_id = mContext.getResources()
- .getIdentifier("success_color", "color", Fingerprint.packageName);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(success_color_id, null));
- int fingerprint_success_id = mContext.getResources()
- .getIdentifier("fingerprint_success", "string", Fingerprint.packageName);
- mErrorTextView.setText(
- mErrorTextView.getResources().getString(fingerprint_success_id));
- mIcon.postDelayed(new Runnable() {
- @Override
- public void run() {
- mCallback.onAuthenticated();
- }
- }, SUCCESS_DELAY_MILLIS);
- }
-
- private void showError(CharSequence error) {
- int ic_fingerprint_error_id = mContext.getResources()
- .getIdentifier("ic_fingerprint_error", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fingerprint_error_id);
- mErrorTextView.setText(error);
- int warning_color_id = mContext.getResources()
- .getIdentifier("warning_color", "color", Fingerprint.packageName);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(warning_color_id, null));
- mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
- mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
- }
-
- Runnable mResetErrorTextRunnable = new Runnable() {
- @Override
- public void run() {
- int hint_color_id = mContext.getResources()
- .getIdentifier("hint_color", "color", Fingerprint.packageName);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(hint_color_id, null));
- int fingerprint_hint_id = mContext.getResources()
- .getIdentifier("fingerprint_hint", "string", Fingerprint.packageName);
- mErrorTextView.setText(
- mErrorTextView.getResources().getString(fingerprint_hint_id));
- int ic_fp_40px_id = mContext.getResources()
- .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName);
- mIcon.setImageResource(ic_fp_40px_id);
- }
- };
-
- public interface Callback {
-
- void onAuthenticated();
-
- void onError();
- }
-}
--- /dev/null
+package de.niklasmerz.cordova.biometric;
+
+public enum PluginError {
+
+ BIOMETRIC_AUTHENTICATION_FAILED(-102, "Authentication failed"),
+ BIOMETRIC_HARDWARE_NOT_SUPPORTED(-104),
+ BIOMETRIC_NOT_ENROLLED(-106),
+ BIOMETRIC_DISMISSED(-108),
+ BIOMETRIC_PIN_OR_PATTERN_DISMISSED(-109),
+ BIOMETRIC_SCREEN_GUARD_UNSECURED(-110,
+ "Go to 'Settings -> Security -> Screenlock' to set up a lock screen"),
+ BIOMETRIC_LOCKED_OUT(-111),
+ BIOMETRIC_LOCKED_OUT_PERMANENT(-112);
+
+ private int value;
+ private String message;
+
+ PluginError(int value) {
+ this.value = value;
+ this.message = this.name();
+ }
+
+ PluginError(int value, String message) {
+ this.value = value;
+ this.message = message;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
--- /dev/null
+package de.niklasmerz.cordova.biometric;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+class PromptInfo {
+
+ private static final String DISABLE_BACKUP = "disableBackup";
+ private static final String TITLE = "title";
+ private static final String SUBTITLE = "subtitle";
+ private static final String DESCRIPTION = "description";
+ private static final String FALLBACK_BUTTON_TITLE = "fallbackButtonTitle";
+ private static final String CANCEL_BUTTON_TITLE = "cancelButtonTitle";
+
+ private Bundle bundle = new Bundle();
+
+ Bundle getBundle() {
+ return bundle;
+ }
+
+ String getTitle() {
+ return bundle.getString(TITLE);
+ }
+
+ String getSubtitle() {
+ return bundle.getString(SUBTITLE);
+ }
+
+ String getDescription() {
+ return bundle.getString(DESCRIPTION);
+ }
+
+ boolean isDeviceCredentialAllowed() {
+ return !bundle.getBoolean(DISABLE_BACKUP);
+ }
+
+ String getFallbackButtonTitle() {
+ return bundle.getString(FALLBACK_BUTTON_TITLE);
+ }
+
+ String getCancelButtonTitle() {
+ return bundle.getString(CANCEL_BUTTON_TITLE);
+ }
+
+ public static final class Builder {
+ private static final String TAG = "PromptInfo.Builder";
+ private Bundle bundle;
+ private boolean disableBackup = false;
+ private String title;
+ private String subtitle = null;
+ private String description = null;
+ private String fallbackButtonTitle = "Use backup";
+ private String cancelButtonTitle = "Cancel";
+
+ Builder(Context context) {
+ PackageManager packageManager = context.getPackageManager();
+ try {
+ ApplicationInfo app = packageManager
+ .getApplicationInfo(context.getPackageName(), 0);
+ title = packageManager.getApplicationLabel(app) + " Biometric Sign On";
+ } catch (PackageManager.NameNotFoundException e) {
+ title = "Biometric Sign On";
+ }
+ }
+
+ Builder(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ public PromptInfo build() {
+ PromptInfo promptInfo = new PromptInfo();
+
+ if (this.bundle != null) {
+ promptInfo.bundle = bundle;
+ return promptInfo;
+ }
+
+ Bundle bundle = new Bundle();
+ bundle.putString(SUBTITLE, this.subtitle);
+ bundle.putString(TITLE, this.title);
+ bundle.putString(DESCRIPTION, this.description);
+ bundle.putString(FALLBACK_BUTTON_TITLE, this.fallbackButtonTitle);
+ bundle.putString(CANCEL_BUTTON_TITLE, this.cancelButtonTitle);
+ bundle.putBoolean(DISABLE_BACKUP, this.disableBackup);
+ promptInfo.bundle = bundle;
+
+ return promptInfo;
+ }
+
+ void parseArgs(JSONArray args) {
+ JSONObject argsObject;
+ try {
+ argsObject = args.getJSONObject(0);
+ } catch (JSONException e) {
+ Log.e(TAG, "Can't parse args. Defaults will be used.", e);
+ return;
+ }
+ disableBackup = getBooleanArg(argsObject, DISABLE_BACKUP, disableBackup);
+ title = getStringArg(argsObject, TITLE, title);
+ subtitle = getStringArg(argsObject, SUBTITLE, subtitle);
+ description = getStringArg(argsObject, DESCRIPTION, description);
+ fallbackButtonTitle = getStringArg(argsObject, FALLBACK_BUTTON_TITLE, "Use Backup");
+ cancelButtonTitle = getStringArg(argsObject, CANCEL_BUTTON_TITLE, "Cancel");
+ }
+
+ private Boolean getBooleanArg(JSONObject argsObject, String name, Boolean defaultValue) {
+ if (argsObject.has(name)){
+ try {
+ return argsObject.getBoolean(name);
+ } catch (JSONException e) {
+ Log.e(TAG, "Can't parse '" + name + "'. Default will be used.", e);
+ }
+ }
+ return defaultValue;
+ }
+
+ private String getStringArg(JSONObject argsObject, String name, String defaultValue) {
+ if (argsObject.optString(name) != null
+ && !argsObject.optString(name).isEmpty()){
+ try {
+ return argsObject.getString(name);
+ } catch (JSONException e) {
+ Log.e(TAG, "Can't parse '" + name + "'. Default will be used.", e);
+ }
+ }
+ return defaultValue;
+ }
+ }
+}
--- /dev/null
+allprojects {
+ repositories {
+ maven { url 'https://jitpack.io' }
+ }
+}
+
+dependencies {
+
+ /**
+ * The android-biometric.aar file has been taken from com.github.exxbrain:android-biometric library.
+ * Android biometric library is a clone of androidx.biometric library adapted for non-androidx apps.
+ * This project could be found at https://github.com/exxbrain/android-biometric.
+ * It has Apache License 2.0.
+ *
+ * TODO: Temporary solution. Should be removed after moving cordova-android to androidx. Then use androidx.biometric.
+ */
+ implementation 'com.github.exxbrain:android-biometric:0.4'
+
+ implementation 'com.android.support:design:28.0.0'
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support:support-v4:28.0.0'
+ implementation 'com.android.support:support-annotations:28.0.0'
+}
+
+android {
+ packagingOptions {
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/LICENSE'
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent" android:layout_height="match_parent">
+
+</FrameLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <style name="TransparentTheme" parent="Theme.AppCompat">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ </style>
+</resources>
\ No newline at end of file
import Foundation
import LocalAuthentication
+
@objc(Fingerprint) class Fingerprint : CDVPlugin {
+ enum PluginError:Int {
+ case BIOMETRIC_UNKNOWN_ERROR = -100
+ case BIOMETRIC_UNAVAILABLE = -101
+ case BIOMETRIC_AUTHENTICATION_FAILED = -102
+ case BIOMETRIC_PERMISSION_NOT_GRANTED = -105
+ case BIOMETRIC_NOT_ENROLLED = -106
+ case BIOMETRIC_DISMISSED = -108
+ case BIOMETRIC_SCREEN_GUARD_UNSECURED = -110
+ case BIOMETRIC_LOCKED_OUT = -111
+ }
+
+ struct ErrorCodes {
+ var code: Int
+ }
+
+
@objc(isAvailable:)
func isAvailable(_ command: CDVInvokedUrlCommand){
let authenticationContext = LAContext();
var biometryType = "finger";
+ var errorResponse: [AnyHashable: Any] = [
+ "code": 0,
+ "message": "Not Available"
+ ];
var error:NSError?;
let policy:LAPolicy = .deviceOwnerAuthenticationWithBiometrics;
-
+ var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Not available");
let available = authenticationContext.canEvaluatePolicy(policy, error: &error);
+ var results: [String : Any]
+
if(error != nil){
biometryType = "none";
+ errorResponse["code"] = error?.code;
+ errorResponse["message"] = error?.localizedDescription;
}
- var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Not available");
- if available == true {
+ if (available == true) {
if #available(iOS 11.0, *) {
switch(authenticationContext.biometryType) {
case .none:
}
pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: biometryType);
+ }else{
+ var code: Int;
+ switch(error!._code) {
+ case Int(kLAErrorBiometryNotAvailable):
+ code = PluginError.BIOMETRIC_UNAVAILABLE.rawValue;
+ break;
+ case Int(kLAErrorBiometryNotEnrolled):
+ code = PluginError.BIOMETRIC_NOT_ENROLLED.rawValue;
+ break;
+
+ default:
+ code = PluginError.BIOMETRIC_UNKNOWN_ERROR.rawValue;
+ break;
+ }
+ results = ["code": code, "message": error!.localizedDescription];
+ pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: results);
}
commandDelegate.send(pluginResult, callbackId:command.callbackId);
@objc(authenticate:)
func authenticate(_ command: CDVInvokedUrlCommand){
let authenticationContext = LAContext();
- var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Something went wrong");
+ var errorResponse: [AnyHashable: Any] = [
+ "message": "Something went wrong"
+ ];
+ var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: errorResponse);
var reason = "Authentication";
var policy:LAPolicy = .deviceOwnerAuthentication;
let data = command.arguments[0] as AnyObject?;
authenticationContext.localizedFallbackTitle = "";
policy = .deviceOwnerAuthenticationWithBiometrics;
} else {
- if let localizedFallbackTitle = data?["localizedFallbackTitle"] as! String? {
- authenticationContext.localizedFallbackTitle = localizedFallbackTitle;
+ if let fallbackButtonTitle = data?["fallbackButtonTitle"] as! String? {
+ authenticationContext.localizedFallbackTitle = fallbackButtonTitle;
+ }else{
+ authenticationContext.localizedFallbackTitle = "Use Pin";
}
}
}
// Localized reason
- if let localizedReason = data?["localizedReason"] as! String? {
- reason = localizedReason;
- }else if let clientId = data?["clientId"] as! String? {
- reason = clientId;
+ if let description = data?["description"] as! String? {
+ reason = description;
}
authenticationContext.evaluatePolicy(
if( success ) {
pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: "Success");
}else {
- // Check if there is an error
- if error != nil {
- pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Error: \(String(describing: error?.localizedDescription))")
+ if (error != nil) {
+
+ var errorCodes = [Int: ErrorCodes]()
+ var errorResult: [String : Any] = ["code": PluginError.BIOMETRIC_UNKNOWN_ERROR.rawValue, "message": error?.localizedDescription ?? ""];
+
+ errorCodes[1] = ErrorCodes(code: PluginError.BIOMETRIC_AUTHENTICATION_FAILED.rawValue)
+ errorCodes[2] = ErrorCodes(code: PluginError.BIOMETRIC_DISMISSED.rawValue)
+ errorCodes[5] = ErrorCodes(code: PluginError.BIOMETRIC_SCREEN_GUARD_UNSECURED.rawValue)
+ errorCodes[6] = ErrorCodes(code: PluginError.BIOMETRIC_UNAVAILABLE.rawValue)
+ errorCodes[7] = ErrorCodes(code: PluginError.BIOMETRIC_NOT_ENROLLED.rawValue)
+ errorCodes[8] = ErrorCodes(code: PluginError.BIOMETRIC_LOCKED_OUT.rawValue)
+
+ let errorCode = abs(error!._code)
+ if let e = errorCodes[errorCode] {
+ errorResult = ["code": e.code, "message": error!.localizedDescription];
+ }
+
+ pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: errorResult);
}
}
self.commandDelegate.send(pluginResult, callbackId:command.callbackId);
- });
+ }
+ );
}
override func pluginInitialize() {
super.pluginInitialize()
}
-}
-
+}
\ No newline at end of file
/*global cordova */
-function Fingerprint() {
-}
+var Fingerprint = function() {
+};
+
+// Plugin Errors
+Fingerprint.prototype.BIOMETRIC_UNKNOWN_ERROR = -100;
+Fingerprint.prototype.BIOMETRIC_UNAVAILABLE = -101;
+Fingerprint.prototype.BIOMETRIC_AUTHENTICATION_FAILED = -102;
+Fingerprint.prototype.BIOMETRIC_SDK_NOT_SUPPORTED = -103;
+Fingerprint.prototype.BIOMETRIC_HARDWARE_NOT_SUPPORTED = -104;
+Fingerprint.prototype.BIOMETRIC_PERMISSION_NOT_GRANTED = -105;
+Fingerprint.prototype.BIOMETRIC_NOT_ENROLLED = -106;
+Fingerprint.prototype.BIOMETRIC_INTERNAL_PLUGIN_ERROR = -107;
+Fingerprint.prototype.BIOMETRIC_DISMISSED = -108;
+Fingerprint.prototype.BIOMETRIC_PIN_OR_PATTERN_DISMISSED = -109;
+Fingerprint.prototype.BIOMETRIC_SCREEN_GUARD_UNSECURED = -110;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT = -111;
+Fingerprint.prototype.BIOMETRIC_LOCKED_OUT_PERMANENT = -112;
+
+// Biometric types
+Fingerprint.prototype.BIOMETRIC_TYPE_FINGERPRINT = "finger";
+Fingerprint.prototype.BIOMETRIC_TYPE_FACE = "face";
+Fingerprint.prototype.BIOMETRIC_TYPE_COMMON = "biometric";
Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
cordova.exec(
{
- "cordova-plugin-fingerprint-aio": {
- "source": {
- "type": "registry",
- "id": "cordova-plugin-fingerprint-aio"
- },
- "is_top_level": true,
- "variables": {
- "FACEID_USAGE_DESCRIPTION": "认证中..."
- }
- },
"cordova-plugin-touch-id": {
"source": {
"type": "registry",
},
"is_top_level": true,
"variables": {}
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "source": {
+ "type": "registry",
+ "id": "cordova-plugin-fingerprint-aio"
+ },
+ "is_top_level": true,
+ "variables": {}
}
}
\ No newline at end of file
"cordova-plugin-advanced-http": {
"PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
},
- "cordova-plugin-fingerprint-aio": {
- "FACEID_USAGE_DESCRIPTION": "认证中...",
- "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
- },
"cordova-plugin-statusbar": {
"PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
},
},
"cordova-plugin-file": {
"PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "FACEID_USAGE_DESCRIPTION": " ",
+ "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
}
},
"dependent_plugins": {
<link rel="stylesheet" type="text/css" href="css/aui.css">
<link rel="stylesheet" type="text/css" href="css/weui.min.css">
<link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
- <title>手机验证码</title>
+ <title>签约</title>
</head>
<body>
<header class="aui-bar aui-bar-nav" style="padding-top:25px;">
<a class="aui-pull-left" href="javascript:window.history.back()">
<span class="aui-iconfont aui-icon-left"></span>
</a>
- <div class="aui-title">手机验证码</div>
+ <div class="aui-title">签约</div>
</header>
<div>
<div class="weui-panel__hd">已发送验证码到您的手机:<span id="phone"></span></div>
</div>
</div>
</div>
+ <div>
+ <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
+ <input id="agree" type="checkbox" class="weui-agree__checkbox" value="1" checked="checked">
+ <span class="weui-agree__text">
+ 我已仔细阅读并同意
+ </span>
+ </label>
+ <a href="signxy.html" style="font-size: 13px;">《市民卡免密代扣签约协议》</a>
+ </div>
<section class="aui-content-padded" style="margin-top: 30px;">
- <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">验证</div>
+ <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">签约</div>
</section>
</div>
</body>
window.localStorage.setItem("idno", idno);
window.localStorage.setItem("phoneX",ret.phonex);
window.localStorage.setItem("personid", ret.personid);
+ window.localStorage.setItem("userid", ret.personid);
window.localStorage.setItem("signed", ret.signed);
window.localStorage.setItem("paypwdset", ret.paypwdset);
- window.location = "bindcheck.html";
+ if(ret.signed=='yes'){
+ window.location = "main.html"
+ }else{
+ window.location = "bindcheck.html";
+ }
+
} else {
if (ret.code == -1) {
$.alert(ret.msg, "提示", function() {
btnTime('codebtn');
},
getCode: function() {
- var name = window.localStorage.getItem("name");
- var cardno = window.localStorage.getItem("cardno");
- var idtype = window.localStorage.getItem("idtype");
- var idno = window.localStorage.getItem("idno");
-
$.showLoading("正在请求");
var param = {
- "cardno": cardno,
- "idtype": idtype,
- "name": name,
- "idno": idno
}
- V1Bindcard(param, function(ok, ret) {
+ V1Bindcardcode(param, function(ok, ret) {
if (ok) {
$.hideLoading();
if (ret.code == 200) {
if(isEmpty(code)){
return;
}
- var personid = window.localStorage.getItem("personid");
+ var agree = $("input[type=checkbox]:checked").val();
+ if(isEmpty(agree)){
+ $.alert("请同意市民卡免密代扣签约协议", "提示");
+ return;
+ }
$.showLoading("正在处理");
var param={
- "personid":personid,
- "code":code,
+ "agree":code
}
- V1Checkcode(param,function(ok,ret){
- if(ok){
- $.hideLoading();
- console.log(ret)
+ V1Signbxy(param,function(ok, ret, err) {
+ if (ok) {
+ $.hideLoading();
if(ret.code==200){
- window.localStorage.setItem("paypwdtype", "new");
- window.localStorage.setItem("userid", personid);
- var signed = window.localStorage.getItem("signed");
- var paypwdset = window.localStorage.getItem("paypwdset");
- console.log(paypwdset)
- if (!paypwdset||'false'==paypwdset) {
- window.location = "paypwdset.html";
- } else {
- if (!isEmpty(signed) && signed == 'yes') {
- window.location = 'main.html'
- } else {
- window.location = 'signxy.html'
- }
- }
+ window.localStorage.setItem("signed",ret.signed);
+ window.location="main.html";
}else{
- $.alert(ret.msg, "错误");
- }
- }else{
+ $.alert(ret.msg, "错误");
+ }
+ } else {
$.hideLoading();
- $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+ $.alert("请求失败了:" + ret.status+"请稍后再试", "错误");
}
})
}
onDeviceReady: function() {
this.receivedEvent('deviceready');
+ this.loginWithFinger();
+ },
+ loginWithFinger:function(){
+ let loginfinger = window.localStorage.getItem("loginfinger");
+ let phone = window.localStorage.getItem("phone");
+ let pwd = window.localStorage.getItem("localpwd");
+ let _this = this;
+ if(phone&&pwd&&loginfinger&&loginfinger=='1'){
+ Fingerprint.isAvailable(function(result){
+ Fingerprint.show({
+ title:"正在使用指纹或人脸登录",
+ description: "请验证您的指纹或人脸"
+ }, function(success){
+ _this.loginIt(phone,pwd);
+ }, function(error){
+ $.alert("验证失败,指纹或人脸错误,请使用密码登录", "提示");
+ //$("#login").removeAttr("checked");
+ });
+
+ }, function(message){
+ $.alert("设备不支持指纹或人脸,请使用密码登录", "提示");
+ });
+ }
},
// Update DOM on a Received Event
if(isEmpty(phone)||isEmpty(pwd)){
return;
}
- //loadingElement('loginBtn', '登录中...')
+ this.loginIt(phone,pwd);
+ },
+ loginIt: function(phone,pwd){
$.showLoading("登录中");
var param={
"username":phone,
window.localStorage.setItem("signed",ret.signed);
window.localStorage.setItem("paypwdset",ret.paypwdset);
window.localStorage.setItem("name",ret.name);
+ window.localStorage.setItem("localpwd",pwd);
window.location = "main.html";
}
}else{
})
})
});
+ $('#accsignbtn').click(function() {
+ app.checkBefore(function() {
+ var signed = window.localStorage.getItem("signed");
+ var cum = new auiDialog({});
+ if (isEmpty(signed) || signed != 'yes') {
+ var confirm = cum.alert({
+ title: "提示",
+ msg: '您尚未签约市民卡免密代扣签约协议,无法使用该功能',
+ buttons: ['取消', '去签约']
+ }, function(ret) {
+ if (ret.buttonIndex == 2) {
+ app.toSignCode();
+ }
+ })
+ }else{
+ window.location = 'signxycheck.html'
+ }
+ })
+ });
this.initData();
this.backBtn();
},
$("#loaddata").show()
$("#nodata").hide();
var param = {
- "pageno": 1
+ "pageno": 1,
+ "platform":device.platform
}
V1Bills(param, function(ok, ret) {
if (ok) {
- //console.log(ret)
+ console.log(ret)
if (ret.code == 200) {
- app.checkVersion(ret.version,ret.minversion,ret.versionmsg);
+ app.checkVersion(ret.version,ret.minversion,ret.versionmsg,ret.versionurl);
+ //app.checkVersion("1.3.9","1","new func","https://shouji.baidu.com/software/26706357.html");
$("#maingt").text(ret.t + "!")
$("#user-amount").text(ret.amount)
$("#user-point").text(ret.point)
}
})
},
- checkVersion:function(ver,minver,msg){
+ checkVersion:function(ver,minver,m,url){
cordova.getAppVersion.getVersionNumber(function (version) {
//alert(version);
- if(version<minver){
- //TODO 强制升级
- alert("当前版本过低,为了不影响您的使用,请先升级");
- }else if(ver>version){
- alert("有新的版本");
+ //alert(version);
+ if(ver>version){
+ var cum = new auiDialog({});
+ var confirm = cum.alert({
+ title: "有新的版本",
+ msg: m,
+ buttons: ['取消', '去更新']
+ }, function(ret) {
+ if (ret.buttonIndex == 2) {
+ cordova.InAppBrowser.open(url, '_system', 'location=no,toolbar=yes,toolbarposition=top,closebuttoncaption=关闭');
+ }
+ })
}
});
},
}
},
checkOther: function(callback) {
- var payseted = window.localStorage.getItem("paypwdset");
var signed = window.localStorage.getItem("signed");
var cum = new auiDialog({});
- console.log(payseted, signed)
- if (isEmpty(payseted) || !payseted || payseted != 'true') {
+
+ if (isEmpty(signed) || signed != 'yes') {
var confirm = cum.alert({
title: "提示",
- msg: '您还没有设置支付密码,无法使用该功能',
- buttons: ['取消', '去设置']
+ msg: '您尚未签约市民卡免密代扣签约协议,无法使用该功能',
+ buttons: ['取消', '去签约']
}, function(ret) {
if (ret.buttonIndex == 2) {
- window.location = 'paypwdset.html'
+ app.toSignCode();
}
})
} else {
- if (isEmpty(signed) || signed != 'yes') {
- var confirm = cum.alert({
- title: "提示",
- msg: '您尚未签约代扣免密付协议,无法使用该功能',
- buttons: ['取消', '去签约']
- }, function(ret) {
- if (ret.buttonIndex == 2) {
- window.location = 'signxy.html'
- }
- })
- } else {
- if (callback) {
- callback()
- }
+ if (callback) {
+ callback()
}
}
},
+ toSignCode: function(){
+ var param = {
+ }
+ V1Bindcardcode(param, function(ok, ret) {
+ if (ok) {
+ if (ret.code == 200) {
+ window.location = 'bindcheck.html'
+ } else {
+ $.alert(ret.msg, "错误");
+ }
+ } else {
+ $.alert("请求失败了 " + ret.status + ",请稍后再试", "错误");
+ }
+ })
+ },
toSign: function() {
window.location = 'signxycheck.html'
},
console.log(err);
});
}
+ document.addEventListener("backbutton", function(e){
+ e.preventDefault();
+ app.backTo();
+ }, false);
},
loadQrcode: function() {
$.showLoading("加载中");
if (ok) {
if (ret.code == 200) {
$.hideLoading();
+ $("#qrcode").html('');
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: ret.qrcode,
width: 200,
document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
},
onDeviceReady: function() {
+ let loginfinger = window.localStorage.getItem("loginfinger");
+ if(loginfinger&&loginfinger=='1'){
+ $("#login").prop("checked","checked");
+ }
},
editPwd: function() {
window.location = "editpwd.html";
},
toPayPwd: function() {
- window.location = "paypwdmng.html";
+ var payseted = window.localStorage.getItem("paypwdset");
+ if (isEmpty(payseted) || !payseted || payseted != 'true') {
+ window.location = 'paypwdset.html'
+ } else{
+ window.location = "paypwdmng.html";
+ }
},
logout:function(){
window.localStorage.removeItem("token");
window.location = "login.html";
},
loginByTouchId: function() {
- Fingerprint.isAvailable(function(result){
- $.alert("设备不支持指纹", "提示");
- }, function(message){
- alert(message);
- });
+ let loginfinger = window.localStorage.getItem("loginfinger");
+ if(loginfinger&&loginfinger=='1'){
+ var confirm = new auiDialog({}).alert({
+ title: "提示",
+ msg: '确定关闭指纹或人脸登录吗?',
+ buttons: ['取消', '确定']
+ }, function(ret) {
+ if (ret.buttonIndex == 2) {
+ window.localStorage.setItem("loginfinger","0");
+ $("#login").removeAttr("checked");
+ }else{
+ //$("#login").attr("checked","checked");
+ }
+ });
+ }else{
+ let pwd = window.localStorage.getItem("localpwd");
+ if(!pwd){
+ $.alert("长时间未登录,需要先登录后再使用该功能", "提示",function(){
+ window.localStorage.removeItem("token");
+ window.location = "login.html";
+ });
+ return;
+ }
+ $("#login").removeAttr("checked");
+ Fingerprint.isAvailable(function(result){
+ Fingerprint.show({
+ title:"大理市民卡开启指纹或人脸登录",
+ description: "请验证您的指纹或人脸"
+ }, function(success){
+ window.localStorage.setItem("loginfinger","1");
+ $.alert("验证成功,您已开启指纹或人脸登录", "提示");
+ $("#login").prop("checked","checked");
+ }, function(error){
+ $.alert("验证失败,指纹或人脸错误次数过多,请稍后再试", "提示");
+ //$("#login").removeAttr("checked");
+ });
+
+ }, function(message){
+ $.alert("设备不支持指纹或人脸", "提示");
+ });
+ }
}
};
app.initialize();
-var dev = true;
+var dev = false;
var SERVER = "https://yy.dlsmk.cn/payapi/mobileapi";
var DOOR_URl = "https://yy.dlsmk.cn/door/app/appMintUIindex";//门禁服务地址
var GLOBAL_TODAY="";
if (dev) {
SERVER = "http://172.28.43.7:8099/payapi/mobileapi";
}
+function V1Bindcardcode(param,callback) {
+ ajaxPost("/v1/bindcardcode", param, callback)
+}
+
function V1Unbindcard(param,callback){
ajaxPost("/v1/unbindcard", param, callback)
}
if(ret.code==200){
$("#content").html(ret.page);
if(isEmpty(ret.signed)||ret.signed!='yes'){
- $("#btn").show();
- $("#content").css("bottom","135px");
+ //$("#btn").show();
+ //$("#content").css("bottom","135px");
}else{
- $("#content").css("bottom","10px");
+ //$("#content").css("bottom","10px");
}
}else{
$.alert(ret.msg, "错误");
--- /dev/null
+var dict;
+var app = {
+
+ // Application Constructor
+ initialize: function() {
+ document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+ },
+ onDeviceReady: function() {
+ var phone = window.localStorage.getItem("phoneX");
+ if(!isEmpty(phone)){
+ $("#phone").text(phone)
+ }else{
+ phone = window.localStorage.getItem("phone");
+ $("#phone").text(phone)
+ }
+ app.getCode();
+ },
+ getCode: function() {
+ $.showLoading("正在请求");
+ var param = {
+ }
+ V1Bindcardcode(param, function(ok, ret) {
+ if (ok) {
+ $.hideLoading();
+ if (ret.code == 200) {
+ $("#codebtn").attr("disabled","disabled")
+ $("#codebtn").addClass("vcodedisabled")
+ btnTime('codebtn');
+ } else {
+ if (ret.code == -1) {
+ $.alert(ret.msg, "提示", function() {
+ window.location = "main.html"
+ });
+ } else {
+ $.alert(ret.msg, "错误");
+ }
+ }
+ } else {
+ $.hideLoading();
+ $.alert("请求失败了 " + ret.status + ",请稍后再试", "错误");
+ }
+ })
+ },
+ doNext: function() {
+ var code = $("#code").val();
+ if(isEmpty(code)){
+ return;
+ }
+ $.showLoading("正在处理");
+ var param={
+ "code":code
+ }
+ V1UnSignbxy(param, function(ok, ret, err) {
+ if (ok) {
+ $.hideLoading();
+ if (ret.code == 200) {
+ window.localStorage.setItem("signed", ret.signed);
+ $.alert('解除成功', "提示", function() {
+ window.location = 'main.html'
+ });
+ } else {
+ $.alert(ret.msg, "错误");
+ }
+ } else {
+ $.hideLoading();
+ $.alert("请求失败了:" + ret.status + "请稍后再试", "错误");
+ }
+ })
+ }
+};
+app.initialize();
\ No newline at end of file
<div class="aui-list-item-right" id="userbank"></div>
</div>
</li>
- <li class="aui-list-item" onclick="app.toSign()">
+ <li class="aui-list-item" id="accsignbtn">
<div class="aui-list-item-label-icon">
<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
</div>
<div style="background: #fff;text-align: center;" id="qrcode"></div>
</div>
<p style="text-align: center;margin-top:40px;color:#999">请将二维码对准扫描设备</p>
- <!--<div style="padding: 30px;">
- <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="window.location.reload();">刷新二维码</div>
- </div>-->
+ <div style="padding: 30px;">
+ <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.refresh()">刷新二维码</div>
+ </div>
</body>
</html>
<script type="text/javascript" src="cordova.js"></script>
</li>
<li class="aui-list-item" onclick="app.loginByTouchId()">
<div class="aui-list-item-label-icon">
- <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+ <i class="aui-iconfont aui-icon-gear aui-text-info"></i>
</div>
<div class="aui-list-item-inner ">
<div class="aui-list-item-title">指纹\人脸登录</div>
- <div class="aui-list-item-right"><input type="checkbox" id="login" class="aui-switch" ></div>
+ <div class="aui-list-item-right"><input type="checkbox" id="login" class="aui-switch" disabled ></div>
</div>
</li>
+ </ul>
+ </section>
+ <section class="aui-content aui-margin-b-15 aui-margin-t-10">
+ <ul class="aui-list aui-list-in aui-margin-t-10 ">
<li class="aui-list-item" onclick="app.toPayPwd()">
<div class="aui-list-item-label-icon">
<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
<link rel="stylesheet" type="text/css" href="css/aui.css">
<link rel="stylesheet" type="text/css" href="css/weui.min.css">
<link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
- <title>签约代扣免密支付协议</title>
+ <title>市民卡免密代扣签约协议</title>
</head>
<body>
<header class="aui-bar aui-bar-nav" style="padding-top:25px;">
- <a class="aui-pull-left" href="main.html">
+ <a class="aui-pull-left" href="javascript:window.history.back()">
<span class="aui-iconfont aui-icon-left"></span>
</a>
- <div class="aui-title">签约代扣免密支付协议</div>
+ <div class="aui-title">市民卡免密代扣签约协议</div>
</header>
- <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:135px;left: 0;right: 0" id="content">
+ <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:10px;left: 0;right: 0" id="content">
</div>
- <div class="weui-footer weui-footer_fixed-bottom" style="background: #fff;display: none;" id="btn">
- <div style="margin-top: 10px;">
- <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
- <input id="agree" type="checkbox" class="weui-agree__checkbox" value="yes">
- <span class="weui-agree__text">
- 我已阅读并同意该协议
- </span>
- </label>
- </div>
- <section class="aui-content-padded" style="margin-top: 20px;">
- <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.agreeXY()">签约代扣协议</div>
- </section>
- </div>
+
</body>
</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+
+<head>
+ <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+ <meta name="format-detection" content="telephone=no">
+ <meta charset="utf-8">
+ <meta name="msapplication-tap-highlight" content="no">
+ <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+ <link rel="stylesheet" type="text/css" href="css/index.css">
+ <link rel="stylesheet" type="text/css" href="css/aui.css">
+ <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+ <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+ <title>解约</title>
+</head>
+<body>
+ <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+ <a class="aui-pull-left" href="javascript:window.history.back()">
+ <span class="aui-iconfont aui-icon-left"></span>
+ </a>
+ <div class="aui-title">解约</div>
+ </header>
+ <div>
+ <div class="weui-panel__hd">已发送验证码到您的手机:<span id="phone"></span></div>
+ <div class="weui-cells weui-cells_form">
+ <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+ <div class="weui-cell__hd">
+ <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+ </div>
+ <div class="weui-cell__bd">
+ <input class="weui-input" type="tel" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+ </div>
+ <div class="weui-cell__ft">
+ <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+ </div>
+ </div>
+ </div>
+ <section class="aui-content-padded" style="margin-top: 30px;">
+ <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">解约</div>
+ </section>
+ </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/unsignedcheck.js"></script>
\ No newline at end of file