in android I use these lines of epr code to create a qrcode, and everything works .. it generates the qrcode readable by my app with the correct data. I'm trying to replicate the same code on Flutter but despite generating the qrcode, it doesn't work. is not detected. probably has some wrong data?
qrCodeWriter = new QRCodeWriter();
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", 1);
jsonObject.put("content", email); // "esertest#clikapptest.it"
String display_name = ContentManager.getInstance(getContext()).getThisAttivita();
if (display_name != null) {
jsonObject.put("display_name", display_name);
} else
jsonObject.put("display_name", ContentManager.getInstance(getContext()).getMerchantData().getIdentifier());
if (scope.equals(Enums.SCOPES.COLLABORATORE.name()))
jsonObject.put("collaborator", DBHelper.getInstance(getActivity()).getSettingsField(DBHelper.SETTINGS_TABLE_FIELD_EMAIL));
jsonObject.put("mac", it.clikapp.toduba.network.Utils.getMacAddress(getContext()));
// BitMatrix bitMatrix = qrCodeWriter.encode(new String(Base64.encode(jsonObject.toString().getBytes(), Base64.DEFAULT)), BarcodeFormat.QR_CODE, iv_qr_code.getWidth(), iv_qr_code.getHeight(), hintsMap);
BitMatrix bitMatrix = qrCodeWriter.encode(Utils.encryptQRCode(ContentManager.getInstance(getContext()).getOauth().getQrCodeKey(), jsonObject.toString()), BarcodeFormat.QR_CODE, width, height, hintsMap);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
//bitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);//guest_pass_background_color
// bitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.WHITE : ContextCompat.getColor(getActivity(), R.color.colorPrimary));
if (getActivity() != null && !getActivity().isFinishing())
bitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : ContextCompat.getColor(getActivity(), R.color.colorPrimary));
}
}
Flutter Version:
Map<String, dynamic> myData = {
'type': 1,
'content': connection.email, //TODO check
'display_name': "${(await contentManager.getUserInfo()).identifier}",
//'collaborator': connection.name, //TODO check
'mac': await Utilities.getDeviceMac(),
};
String encodedJson = jsonEncode(myData);
You can use a flutter plugin to add QR Scanning capabilities in your app
refer to this link
Future _scanBytes() async {
try {
String barcode = await scanner.scan();
setState(() => this.barcode = barcode);
} on PlatformException catch (e) {
if (e.code == scanner.CameraAccessDenied) {
setState(() {
this.barcode = 'The user did not grant the camera permission!';
});
} else {
setState(() => this.barcode = 'Unknown error: $e');
}
} on FormatException{
setState(() => this.barcode = 'null (User returned using the "back"-button before scanning anything. Result)');
} catch (e) {
setState(() => this.barcode = 'Unknown error: $e');
}
print("barcode "+barcode);
}
Related
I am attempting to use tesseract in Xamarin.Forms for text character recognition on images. On Android, I've implemented the logic using the steps below;
Grab bitmaps of the TextureView.
Convert bitmaps to black and white.
Crop needed from the bitmap image
Set tesseract image with cropped image
Currently facing memory issues and haven't got a way around it so far
Snippets below show the main functions of the code.
public async void takeContinuousPhotos(){
byte[] newBytes;
byte[] bytes;
while (ocrTextChosen == false){
bytes = await CapturePhoto();
newBytes = this.CropPhoto(bytes, new System.Drawing.Rectangle(40, view.Height / 2 - 200, view.Width - 40, 100), (view.Width - 40) * 2, 200);
if (!_tesseract.Initialized)
{
await _tesseract.Init("eng");
var result = await _tesseract.SetImage(new MemoryStream(newBytes));
if (result)
{
Device.BeginInvokeOnMainThread(() => {
this.ocrText.Text = this._tesseract.Text;
});
_tesseract.Clear();
bytes = new byte[0];
newBytes = new byte[0];
}
}
else {
var result = await _tesseract.SetImage(new MemoryStream(newBytes));
if (result)
{
Device.BeginInvokeOnMainThread(() => {
this.ocrText.Text = this._tesseract.Text;
});
_tesseract.Clear();
bytes = new byte[0];
newBytes = new byte[0];
}
}
}
}
// Capture photo from stream
public async Task<byte[]> CapturePhoto()
{
var ratio = ((decimal)Height) / Width;
var blackwhiteBitmap = this.toGrayscale(liveView.Bitmap);
var image = Bitmap.CreateBitmap(blackwhiteBitmap, 0, 0, blackwhiteBitmap.Width, (int)(blackwhiteBitmap.Width * ratio));
byte[] imageBytes = null;
using (var imageStream = new System.IO.MemoryStream())
{
await image.CompressAsync(Bitmap.CompressFormat.Jpeg, 10, imageStream);
image.Recycle();
imageBytes = imageStream.ToArray();
imageStream.Dispose();
}
image = null;
return imageBytes;
}
takeContinuousPhotos() is then run on the TextureView delegate method as shown below:
public void OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
camera = Android.Hardware.Camera.Open();
var parameters = camera.GetParameters();
var aspect = ((decimal)height) / ((decimal)width);
var previewSize = parameters.SupportedPreviewSizes
.OrderBy(s => System.Math.Abs(s.Width / (decimal)s.Height - aspect))
.First();
parameters.SetPreviewSize(previewSize.Width, previewSize.Height);
parameters.FocusMode = Android.Hardware.Camera.Parameters.FocusModeContinuousPicture;
camera.SetParameters(parameters);
camera.SetPreviewTexture(surface);
StartCamera();
Task.Run(() => {
this.takeContinuousPhotos();
});
}
Help me guys, I'm creating augmented reality (unity+vuforia). I have button for screen shot screen, is work but file location on (/Data/Data/com.companyname.gamename/Files). How to change folder? (storage/emulated/0/DCIM/Camera/) .
using UnityEngine;
using System.Collections;
using System.IO;
public class SnapshotShare : MonoBehaviour
{
private AndroidUltimatePluginController androidUltimatePluginController;
Camera mainCamera;
RenderTexture renderTex;
Texture2D screenshot;
Texture2D LoadScreenshot;
int width = Screen.width;
int height = Screen.height;
string fileName;
string screenShotName = "Animal3D_";
void Start ()
{
androidUltimatePluginController = AndroidUltimatePluginController.GetInstance ();
}
public void Snapshot ()
{
StartCoroutine (CaptureScreen ());
}
public IEnumerator CaptureScreen ()
{
yield return null;
GameObject.Find ("Canvas").GetComponent<Canvas> ().enabled = false;
yield return new WaitForEndOfFrame ();
if (Screen.orientation == ScreenOrientation.Portrait || Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
mainCamera = Camera.main.GetComponent<Camera> ();
renderTex = new RenderTexture (height, width, 24);
mainCamera.targetTexture = renderTex;
RenderTexture.active = renderTex;
mainCamera.Render ();
screenshot = new Texture2D (height, width, TextureFormat.RGB24, false);
screenshot.ReadPixels (new Rect (0, 0, height, width ), 0, 0);
screenshot.Apply ();
RenderTexture.active = null;
mainCamera.targetTexture = null;
}
if (Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.LandscapeRight) {
mainCamera = Camera.main.GetComponent<Camera> ();
renderTex = new RenderTexture (width, height, 24);
mainCamera.targetTexture = renderTex;
RenderTexture.active = renderTex;
mainCamera.Render ();
screenshot = new Texture2D (width, height, TextureFormat.RGB24, false);
screenshot.ReadPixels (new Rect (0, 0, width, height), 0, 0);
screenshot.Apply (); //false
RenderTexture.active = null;
mainCamera.targetTexture = null;
}
File.WriteAllBytes (Application.persistentDataPath + "/" +screenShotName+Time.frameCount+".jpg", screenshot.EncodeToJPG ());
GameObject.Find ("Canvas").GetComponent<Canvas> ().enabled = true;
}
public void LoadImage ()
{
string path = Application.persistentDataPath + "/" + screenShotName;
byte[] bytes;
bytes = System.IO.File.ReadAllBytes(path);
LoadScreenshot = new Texture2D(1,1);
LoadScreenshot.LoadImage(bytes);
GameObject.FindGameObjectWithTag ("Picture").GetComponent<Renderer> ().material.mainTexture = screenshot;
}
public void close ()
{
Application.Quit ();
}
}
Took from here (more details) and here (discussion).
I suggest you to save your captured screenshot in app location (/Data/Data/com.companyname.gamename/Files) and then use File.Move(source, dest) to move it:
if(Shot_Taken == true)
{
string Origin_Path = System.IO.Path.Combine(Application.persistentDataPath, Screen_Shot_File_Name);
// This is the path of my folder.
string Path = "/mnt/sdcard/DCIM/Inde/" + Screen_Shot_File_Name;
if(System.IO.File.Exists(Origin_Path))
{
System.IO.File.Move(Origin_Path, Path);
Shot_Taken = false;
}
}
In my app I have received a base64 string that represents a PDF. I want the user to be able to save the base64 as a pdf to his phone. I have been looking in to the cordova-file-transfer plugin but that requires a (server)path where the file can be downloaded from, instead of converting a base64 string.
Has anybody succeeded in downloading a pdf in phonegap using a base64 string?
After some more searching and trying I found something that worked.
Converting base64 to pdf blob
//Helper function that converts base64 to blob
function b64toBlob(b64Data, contentType, sliceSize) {
var input = b64Data.replace(/\s/g, ''),
byteCharacters = atob(input),
byteArrays = [],
offset, slice, byteNumbers, i, byteArray, blob;
contentType = contentType || '';
sliceSize = sliceSize || 512;
for (offset = 0; offset < byteCharacters.length; offset += sliceSize) {
slice = byteCharacters.slice(offset, offset + sliceSize);
byteNumbers = new Array(slice.length);
for (i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
//Convert to blob.
try {
blob = new Blob(byteArrays, { type: contentType });
}
catch (e) {
// TypeError old chrome, FF and Android browser
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder) {
var bb = new BlobBuilder();
for (offset = 0; offset < byteArrays.length; offset += 1) {
bb.append(byteArrays[offset].buffer);
}
blob = bb.getBlob(contentType);
}
else if (e.name == "InvalidStateError") {
blob = new Blob(byteArrays, {
type: contentType
});
}
else {
return null;
}
}
return blob;
};
And then the downloading itself we need the cordova-file plugin:
var fileToSave= b64toBlob(fileData, 'application/pdf');
writeFile();
function writeFile() {
console.log("request file system");
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemRetrieved, onFileSystemFail);
}
function onFileSystemRetrieved(fileSystem) {
console.log("file system retrieved");
fileSystem.root.getFile(fileName, { create: true }, onFileEntryRetrieved, onFileSystemFail);
}
function onFileEntryRetrieved(fileEntry) {
console.log("file entry retrieved");
fileEntry.createWriter(gotFileWriter, onFileSystemFail);
}
function gotFileWriter(writer) {
console.log("write to file");
writer.onwrite = function (evt) {
alert('done');
}
writer.write(fileToSave);
window.open(fileName, '_blank');
}
function onFileSystemFail(error) {
console.log(error.code);
alert(error.code)
}
Code to generate Qr code using zxing is ---
It takes string data and the imageview This works just fine
private void generateQRCode_general(String data, ImageView img)throws WriterException {
com.google.zxing.Writer writer = new QRCodeWriter();
String finaldata = Uri.encode(data, "utf-8");
BitMatrix bm = writer.encode(finaldata, BarcodeFormat.QR_CODE,150, 150);
Bitmap ImageBitmap = Bitmap.createBitmap(150, 150,Config.ARGB_8888);
for (int i = 0; i < 150; i++) {//width
for (int j = 0; j < 150; j++) {//height
ImageBitmap.setPixel(i, j, bm.get(i, j) ? Color.BLACK: Color.WHITE);
}
}
if (ImageBitmap != null) {
qrcode.setImageBitmap(ImageBitmap);
} else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.userInputError),
Toast.LENGTH_SHORT).show();
}
}
Now my question is ,how to get bar code using the same library.i saw some files related to bar codes but i am not sure how to do it.
Since I want to generate the bar code within the application and not call any web service. Since i am already using zxing,no point in including itext and barbecue jars
Like Gaskoin told... MultiFormatWrite it worked :) here is the code.
com.google.zxing. MultiFormatWriter writer =new MultiFormatWriter();
String finaldata = Uri.encode(data, "utf-8");
BitMatrix bm = writer.encode(finaldata, BarcodeFormat.CODE_128,150, 150);
Bitmap ImageBitmap = Bitmap.createBitmap(180, 40,Config.ARGB_8888);
for (int i = 0; i < 180; i++) {//width
for (int j = 0; j < 40; j++) {//height
ImageBitmap.setPixel(i, j, bm.get(i, j) ? Color.BLACK: Color.WHITE);
}
}
if (ImageBitmap != null) {
qrcode.setImageBitmap(ImageBitmap);
} else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.userInputError),
Toast.LENGTH_SHORT).show();
}
I've tested the accepted answer to generate a Barcode but the output is blurry when used in a big ImageView. To get a high quality output, the width of the BitMatrix, the Bitmap and the final ImageView should be the same. But doing so using the accepted answer will make the Barcode generation really slow (2-3 seconds). This happens because
Bitmap.setPixel()
is a slow operation, and the accepted answer is doing intensive use of that operation (2 nested for loops).
To overcome this problem I've modified a little bit the Bitmap generation algorithm (only use it for Barcode generation) to make use of Bitmap.setPixels() which is much faster:
private Bitmap createBarcodeBitmap(String data, int width, int height) throws WriterException {
MultiFormatWriter writer = new MultiFormatWriter();
String finalData = Uri.encode(data);
// Use 1 as the height of the matrix as this is a 1D Barcode.
BitMatrix bm = writer.encode(finalData, BarcodeFormat.CODE_128, width, 1);
int bmWidth = bm.getWidth();
Bitmap imageBitmap = Bitmap.createBitmap(bmWidth, height, Config.ARGB_8888);
for (int i = 0; i < bmWidth; i++) {
// Paint columns of width 1
int[] column = new int[height];
Arrays.fill(column, bm.get(i, 0) ? Color.BLACK : Color.WHITE);
imageBitmap.setPixels(column, 0, 1, i, 0, 1, height);
}
return imageBitmap;
}
This approach is really fast even for really big outputs and generates a high quality bitmap.
You are using QRCodeWriter. If you want to write another type of code, use another Writer.
Check this MultiFormatWriter - it can write any type of bar or find specific writers here in subfolders (this is from zxing library)
There you go,
public static Bitmap createBarCode (String codeData, BarcodeFormat barcodeFormat, int codeHeight, int codeWidth) {
try {
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel> ();
hintMap.put (EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
Writer codeWriter;
if (barcodeFormat == BarcodeFormat.QR_CODE) {
codeWriter = new QRCodeWriter ();
} else if (barcodeFormat == BarcodeFormat.CODE_128) {
codeWriter = new Code128Writer ();
} else {
throw new RuntimeException ("Format Not supported.");
}
BitMatrix byteMatrix = codeWriter.encode (
codeData,
barcodeFormat,
codeWidth,
codeHeight,
hintMap
);
int width = byteMatrix.getWidth ();
int height = byteMatrix.getHeight ();
Bitmap imageBitmap = Bitmap.createBitmap (width, height, Config.ARGB_8888);
for (int i = 0; i < width; i ++) {
for (int j = 0; j < height; j ++) {
imageBitmap.setPixel (i, j, byteMatrix.get (i, j) ? Color.BLACK: Color.WHITE);
}
}
return imageBitmap;
} catch (WriterException e) {
e.printStackTrace ();
return null;
}
}
Of course you can support as many BarcodeFormats as you want, just change the constructor here :
Writer codeWriter;
if (barcodeFormat == BarcodeFormat.QR_CODE) {
codeWriter = new QRCodeWriter ();
} else if (barcodeFormat == BarcodeFormat.CODE_128) {
codeWriter = new Code128Writer ();
} else {
throw new RuntimeException ("Format Not supported.");
}
try this code
Context context = getActivity();
Intent intent = new Intent("com.google.zxing.client.android.ENCODE");
intent.putExtra("ENCODE_TYPE", Text);
intent.putExtra("ENCODE_DATA", "12345678901");
intent.putExtra("ENCODE_FORMAT", "UPC_A");
startActivity(intent);
hope this helps you.
I am trying to get a "Please wait..." message to display when I make an ajax call to get information. Basically, the user puts in their search term, hits Search, I want to display "Please wait..." while the page is doing the ajax call, then hide it once it is done.
I have a div on my jsp page that looks like this:
<div id="modalWindow">Please Wait...</div>
My jQuery looks like this:
jQuery('#modalWindow').css({
'text-align' : 'center',
'font-size' : '20px'
}).hide(); //this is called when the page initially loads
jQuery('#modalWindow').show(); //I call this in the function that does the Ajax call
jQuery('#modalWindow').hide(); //I call this once the Ajax is done.
This is my entire Ajax call:
jQuery.ajax(
{
url : urlContext + "/getItems.html",
data :
{
txtItemReference : txtItemReference
},
dataType : "json",
cache : false,
async : false,
timeout : 100000,
success : function(jsonResponse)
{
if ( jsonResponse instanceof Object)
{
if (jQuery.isEmptyObject(jsonResponse))
{
createLocationDisplayPanel(false);
createSimilarItemsPanel(false);
}
else if (jsonResponse['Locations'] != undefined)
{
responseArray = new Array();
arrayStart = 0;
intPage = 1;
if (jsonResponse['Locations'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Locations'].length; x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
else
{
responseArray = new Array();
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
createLocationDisplayPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
else
{
if (jsonResponse['Items'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Items'].length; x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
else
{
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
createSimilarItemsPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
if (callback != undefined)
{
callback();
}
}
else
{
alertLogout(document.URL);
}
},
error : function(jsonResponse)
{
if (jsonResponse.hasOwnProperty('ERROR'))
{
alertError("There was no response from the server.");
}
}
});
This works perfectly in Firefox on my desktop as well as Firefox for Android. However, on every Android browser I've tried, the "Please wait..." text never displays, and I am getting frustrated. Can anyone please tell me the workaround to get the show() and hide() functions to work in an Android browser? Thanks.
Have you checked if jQuery is loaded at that point? Write this before your script.
if (typeof jQuery == 'undefined') {
alert('jQuery is not loaded');
}
You might need to combine the scripts or find a way to ensure they are loaded in the order you need them.
I found the issue was with the async property of the Ajax call:
jQuery.ajax(
{
url : urlContext + "/getItems.html",
data :
{
txtItemReference : txtItemReference
},
dataType : "json",
cache : false,
async : true, //was false before
timeout : 100000,
success : function(jsonResponse)
{
if ( jsonResponse instanceof Object)
{
if (jQuery.isEmptyObject(jsonResponse))
{
createLocationDisplayPanel(false);
createSimilarItemsPanel(false);
}
else if (jsonResponse['Locations'] != undefined)
{
responseArray = new Array();
arrayStart = 0;
intPage = 1;
if (jsonResponse['Locations'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Locations'].length; x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
else
{
responseArray = new Array();
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
createLocationDisplayPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
else
{
if (jsonResponse['Items'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Items'].length; x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
else
{
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
createSimilarItemsPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
if (callback != undefined)
{
callback();
}
}
else
{
alertLogout(document.URL);
}
},
error : function(jsonResponse)
{
if (jsonResponse.hasOwnProperty('ERROR'))
{
alertError("There was no response from the server.");
}
}
});
Once I changed that, the show and hide worked in Android. Thanks for the help guys.