I want to develop the function of recognizing bank card numbers. The recognition effect of card.io is much better for cards with raised numbers than those without raised numbers. What other open-source projects can be used to recognize bank card numbers? Here I'd like to share with you the bank card recognition service of HUAWEI ML Kit that I once used in one of my projects. It is free of charge. This service can correctly recognize the card numbers and validity periods of popular cards such as JCB, China UnionPay, American Express, Visa, and Mastercard, regardless of whether the card numbers are raised. The size of the SDK is about 3 MB, which is smaller than that of card.io.
The integration procedure is as follows:
Step 1: Set recognition parameters and call the API for recognition.
Code:
private void startCaptureActivity(MLBcrCapture.Callback callback) {
MLBcrCaptureConfig config = new MLBcrCaptureConfig.Factory()
// Specify that only the card number and validity period are recognized and returned.
.setResultType(MLBcrCaptureConfig.RESULT_SIMPLE)
// Set the display orientation of the recognition screen to be self-adaptive.
.setOrientation(MLBcrCaptureConfig.ORIENTATION_AUTO)
.create();
MLBcrCapture bankCapture = MLBcrCaptureFactory.getInstance().getBcrCapture(config);
bankCapture.captureFrame(this, callback);
}
Step 2: Obtain the recognition result.
Code:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.detect:
startCaptureActivity(callback);
break;
default:
break;
}
}
As shown in the following figure, the recognition speed is fast. The card can be quickly recognized as long as it is in the scanning box, even if the card is not placed in a proper position. This service does not require the user to align the card to the boundaries.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
[/SIZE]
Related
See the example hierarchy attached. There is a flow up and down. Using the app would go something like this:
Select Team 1 on the Home activity --> Activity A inflates based on the selection.
Select Player 2 on Activity A --> Activity B inflates based on the selection.
Select to Add a Stat on Activity B --> Activity C inflates and allows a stat to be added.
User returns to Activity B, which must maintain the Player 2 context and update based on C.
User returns to Activity A, which must maintain the Team 1 context and updated based on B.
User returns to Home, which must update based on A.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
My question is how to update an activity based on its child while maintaining the context supplied by its parent.
For example, let's focus on Activity B. It knows to inflate for Player 1 because this info was passed from Activity A in an intent.
If I were to go to Activity C and press Back, B wouldn't update.
If I were to go to C and press Up, B would crash because it would try to make a new instance and wouldn't know what player to inflate (defined in onCreate()).
I tried declaring B with a "singleTop" launchMode, but then it just restarts and doesn't update based on C's info. Based on my limited experience/research, I see the following options.
Store an Activity's inflater variables as static (so they won't be "lost" when creating a new instance)
Initiate my view inflation (via Fragment) in the Activity's onStart() method so that it would refresh when Restarting. (Would this help? What about the fact that all of my inflation happens inside of a fragment? I fear the Lifecycle gods.)
I'm new to a lot of this and would appreciate any help. Thanks!
Hi everyone!
In this post I will introduce a Command Line Interface that I published to create H5 to QuickApps in a different way.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
As in the above figure, my aim was to write one-line to create a quick app and then input application parameters with an interactive way.
Basically this commands can be used to create a single app:
Code:
npx [user=10925755]@onurkenis[/user]/create-quick-app # run via npx without installing
In another way, we can define properties inline and missing properties will be asked respectively, just like in the previous figure.
Code:
npx [user=10925755]@onurkenis[/user]/create-quick-app
--appName="My App"
--packageName=com.onurkenis.myApp
--url=https://github.com/onurkenis/create-quick-app
--icon=./icon.png
There is another mode to create quick apps which is batch app creation. This mode allows us to give a json file instead of app properties and we are able to create many projects at once that we added to our json file.
This is the structure of the JSON file and number of applications to add is up to us.
Code:
{
"projects": [
{
"appName": "TestApp1",
"packageName": "com.onurkenis.one",
"url": "https://github.com/onurkenis/create-quick-app",
"icon": "C:/Pictures/optional_icon.jpg"
},
{
"appName": "TestApp2",
"packageName": "com.onurkenis.two",
"url": "https://github.com/onurkenis/create-quick-app"
},
{
"appName": "TestApp3",
"packageName": "com.onurkenis.three",
"url": "https://github.com/onurkenis/create-quick-app"
}
]
}
To create multiple QuickApps with the created JSON, this commands can be triggered:
Code:
npx [user=10925755]@onurkenis[/user]/create-quick-app --fromJson=path_of_json # run via npx without installing
To get rpk file, you can do followings and check PROJECT_PATH/dist folder.
Code:
cd PROJECT_PATH
npm install
npm run release
If you want to check out my project in github or npm, here are the links.
Github: /onurkenis/create-quick-app
Npm: /@onurkenis/create-quick-app
All suggestions are welcomed.
Thanks.
Symptom:
When the getRankingIntent API is called, which is related to leaderboards, the following error message is displayed.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Log Information
The following error information is displayed in the Android Studio Logcat logs:
HTML:
2020-10-22 11:14:17.831 27218-3850/com.huawei.gameassistant W/HwGameAssistant-10.6.0.301-RequestHelper: client.assistant.gs.leaderboard.scores reponse fail code:502, msg:Bad Gateway
2020-10-22 11:14:17.831 27218-3850/com.huawei.gameassistant E/HwGameAssistant-10.6.0.301-GameRankingScoreListViewModel: getHttpStatusCode is : 502
Troubleshooting
The test result shows that the game sign-in function is normal. Therefore, the problem is not caused by a network error. After studying relevant documents, we checked the following items:
1. First, we ensured that the package name and app ID belong to the same game.
2. Then, we checked whether leaderboards have been created for the game in HUAWEI AppGallery Connect. It was found that leaderboards have been added for another game. We attempted to resolve the problem. However, testing shows that the problem still persists.
3. Finally, it was found that the account we used for testing is not on the list of test accounts in AppGallery Connect. After adding it to the list and clearing HMS Core (APK) cache on the phone, the problem is solved.
Summary:
If you find that the leaderboard function is abnormal, ensure that:
The app ID and the package name belong to the same game.
Your game has its leaderboard data created in AppGallery Connect.
Your test account has been added in AppGallery Connect.
For more details, check:
Adding a Leaderboard:
https://developer.huawei.com/consumer/en/doc/distribution/app/agc-add_leaderboard
Managing Tester Accounts:
https://developer.huawei.com/consumer/en/doc/distribution/app/agc-tester_account_mgt
Question:
How to use LayaAir IDE to split the package of a quick game and load subpackages?
Guide:
Splitting the package of a Huawei quick game and loading its subpackages help reduce the traffic and time required for app download. By doing so, you can choose to load or download specific subpackages, instead of the whole package at a time.
Procedure:
1. Release a subpackage in LayaAir IDE.
To split a package, select Set the subcontract during project release, as shown in the following figure.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Then, click the plus sign (+) below. The following window is displayed. Set the subpackage name and the corresponding folder.
2. Configure subpackage information in the manifest file.
You also need to set parameters for the subpackages in the manifest.json file. The sample code is as follows:
Note: If you split a resource package manually, the values of resource should end with a slash (/). In addition, a game.js file must exist in the directory. (Skip this step if you let LayaAir IDE split the package for you.)
XML:
subpackages:[
{
"name":"subpackageName1",// Subpackage name.
"resource":"subpackagePath1"// Corresponding subpackage directory.
},
{
"name":"subpackageName2", // Subpackage name.
"resource":"subpackagePath2"// Corresponding subpackage directory.
}
]
3. Apply specific subpackages.
The sample code for using specific subpackages is as follows:
JavaScript:
var task = hbs.loadSubpackage({
subpackage:'subpackageName1',
success : function () {
console.log("loadSubpackage success" );
},
fail:function(){
console.log("loadSubpackage fail");
},
complete:function() {
console.log("loadSubpackage complete");
}
});
task.onprogress(
callback(res) {
console.log("onProgress" + JSON.stringify(res));
}
);
PHP — Signature Verification for HUAWEI IAP
Background
If you integrate the HMS SDK 3.x, and after a successful purchase, you can obtain the purchase data InAppPurchaseData and its signature data from the PurchaseResultInfo object. You need to use the public key allocated by AppGallery Connect to verify the signature.
For details, check this document:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/dev-guide-0000001050130254#EN-US_TOPIC_0000001050130254__section183174113342
Code Development
I wrote the sample code to verify the obtained purchase data, its signature and the public key for your reference. Hope it can help you with problem locating.
Sample code:
PHP:
<?php
// Actual payment callback result. Copy the original data without any processing.
// Here, I replaced some personal information with xxxx.
$content = '{"autoRenewing":false,"orderId":"201912250949586652ebf220c1.10xxxx75","packageName":"com.example.xxxxxxexample_netease.huawei","applicationId":10xxxx75,"kind":0,"productId":"3","productName":"test33333","purchaseTime":1577238608000,"purchaseTimeMillis":1577238608000,"purchaseState":0,"developerPayload":"09815772385983110000000191996123","purchaseToken":"0000016f3abf3a78a4ef7b217523ea5a346825ab632c152b864c2e5251433c9d599c5986ab8c89b1.1.10xxxx75","consumptionState":0,"acknowledged":0,"currency":"CNY","price":100,"country":"CN","payOrderId":"Aed0f1fbd9929f803d9d23b523b14575","payType":"4"}';
// The sign value must be the original value in the callback. Do not urlencode or urldecode the value.
$sign = 'IuCnJI3bCDr92uomUbxamp6VeC8vN+o3GTtB7aVwTGpkk9QgeR9KdUjDya1tJXKX8HZgTTLpj7v4A1lP8xrOq3+knykn32Tup6STnn4qpee8J3sS9kjpIHmhIbh3QfnsHksCaT4ib9BurIWnH7yEtNlwqmOOibJw8FgFXofrfPsDwjuCy4/X9rlbimjmyAiFZLXCTNQoGollqUVEjqabhjh/a+VY89A6Z02F2bJkes39a7lQMer42egha86w65L3UYYSLOyxQPIfIZ1BG5yirZN4JgcD17CMk+vQvtVDXhC+e4xN//txWlG/qIgviZbmhLFGjA/gfP0o8LpY7booiA==';
// The payment public key type needs to be RSA. A link break is added to every 64 characters in the intermediate content.
$pubKey = '-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq7iOD9qLMxMCEsY+l+IE
6kdI9HKHQoDG29ebPZFD+U1pdDewmkEcQzv/k0NmE9oeNIcxUqhg7ZwRrQ0g9xje
BCkiLTg4DOygOPOcZykuKZXDv/9aFn6FR5BVCrrOzmeR+/aEYcZZp86iWX+W4BdJ
L41i8qYonVRD6sDNuidAdg0UkNMPVRiHd5EYBgRHpPma7oeRVqfX4Iq/rL4DFOpu
uLiaLKmWSMOCLnIH+EXjjw3ttJOrB4Rq2fq6KrORgc8JMq2TPf/kK6r8NW9eWRWa
zmFvAZ8bUA7Idu4W8Z4SENwEO+ZeyWQx5I/piYEmBvmn3dy2l2bP3cZMUBVACkAE
jwIDAQAB
-----END PUBLIC KEY-----';
$openssl_public_key = @openssl_get_publickey($pubKey);
// Whether to use the SHA-256 algorithm depends on the value of signType in the callback result. Add the following code when signType is set to RSA256. In other situations, the signature algorithm needs to be SHA1.
$ok = @openssl_verify($content, base64_decode($sign), $openssl_public_key,'SHA256');
@openssl_free_key($openssl_public_key);
$result = "";
if($ok)
{
$result = "0";// success
}
else
{
$result = "1";// failure
}
$res = "{ \"result\": $result} ";
echo $res;
?>
Running the Code
Search for an online code runner that supports PHP. For example:
https://tool.lu/en_US/coderunner/
If the value 0 is returned, everything is normal.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}