I'm developing an app for Android using Xamarin and EMDK for a Zebra TC51.
The problem is I'm able to trigger the barcode scanner (using the physical button) only once. After that, the scanner does not run anymore.
What can be the cause of that? What can I check to have a diagnostic?
Extract of the code:
Tracking of the status:
scanner.Status += ( s, e ) =>
{
try
{
StatusData statusData = e.P0;
StatusData.ScannerStates state = e.P0.State;
this.RunOnUiThread( () => StateMessage( "Scanner state : " + state.Name() ) );
}
catch ( System.Exception exc )
{
this.RunOnUiThread( () => StateMessage( "Scanner state exception : " + exc.Message ) );
}
};
and for received data:
scanner.Data += ( s, e ) =>
{
try
{
var statusData = e.P0;
var scanData = e.P0.GetScanData();
foreach ( var sd in scanData )
{
this.RunOnUiThread( () => StateMessage( "Scanned : " + sd.Data ) );
}
}
catch ( System.Exception exc )
{
this.RunOnUiThread( () => StateMessage( "Scanner data exception : " + exc.Message ) );
}
};
The state sequence I can trace is the following:
Before triggering: waiting, idle, waiting
After triggering: scanning, idle
After that nothing. The result is the same if I effectively read a barcode (and I can read it once) or not (just triggering the button).
you need to call read() again every time the scanner goes into the IDLE state to enable continuous scanning. There is a Xamarin sample app that you should be able to follow at https://github.com/Zebra/samples-emdkforxamarin-2_5/blob/BarcodeSample1/BarcodeSample1/BarcodeSample1/MainActivity.cs
Related
Currently working on xamarin and trying to connect a scanner device(Zebra scanner) via bluetooth. CoreBluetooth.CBPeripheral is used to get information of device like id, name etc…
To scan device used following code :
protected override async Task StartScanningForDevicesNativeAsync(Guid[] serviceUuids, bool allowDuplicatesKey, CancellationToken scanCancellationToken)
{
// Wait for the PoweredOn state
await WaitForState(CBCentralManagerState.PoweredOn, scanCancellationToken).ConfigureAwait(false);
if (scanCancellationToken.IsCancellationRequested)
throw new TaskCanceledException("StartScanningForDevicesNativeAsync cancelled");
Trace.Message("Adapter: Starting a scan for devices.");
CBUUID[] serviceCbuuids = null;
if (serviceUuids != null && serviceUuids.Any())
{
serviceCbuuids = serviceUuids.Select(u => CBUUID.FromString(u.ToString())).ToArray();
Trace.Message("Adapter: Scanning for " + serviceCbuuids.First());
}
DiscoveredDevices.Clear();
_centralManager.ScanForPeripherals(serviceCbuuids, new PeripheralScanningOptions { AllowDuplicatesKey = allowDuplicatesKey });
}
And getting Response in Event by following code :
_centralManager.DiscoveredPeripheral += (sender, e) =>
{
Trace.Message("DiscoveredPeripheral: {0}, Id: {1}", e.Peripheral.Name, e.Peripheral.Identifier);
System.Diagnostics.Debug.WriteLine("DiscoveredPeripheral: {0}, Id: {1}", e.Peripheral.Name, e.Peripheral.Identifier);;
var name = e.Peripheral.Name;
foreach (var oData in e.AdvertisementData)
{
System.Diagnostics.Debug.WriteLine("AdvertisementData : key : " + oData.Key + " , Value : " + oData.Value);
}
if (e.AdvertisementData.ContainsKey(CBAdvertisement.DataLocalNameKey))
{
// iOS caches the peripheral name, so it can become stale (if changing)
// keep track of the local name key manually
name = ((NSString)e.AdvertisementData.ValueForKey(CBAdvertisement.DataLocalNameKey)).ToString();
}
var device = new Device(this, e.Peripheral, name, e.RSSI.Int32Value,
ParseAdvertismentData(e.AdvertisementData));
HandleDiscoveredDevice(device);
};
Now, in this AdvertisementData doesn’t contains CBAdvertisement.DataLocalNameKey so not able to get device name…?
1) My Environment:
. Windows 10 Pro (licensed) - 64 bits - 8GB Ram;
. AutoCAD (licensed) 2014/2015/2016/2017 64 bits (all HOTFIX and SERVICEPACK installed);
. Visual Studio 2010 Express Edition (for AutoCAD 2014);
. Visual Studio 2013 (for AutoCAD 2015/2016/2017);
. Antivirus : only Windows Defender.
2) Visual Studio 2013 Solution
nuGet packages:
System.Data.SQLite
SpatialiteSharp
Target: .NET 4.5
3) Database used for this test
. Database name : 'dbtest.sqlite', download here and save to c:\temp
. Database table : 'tb_test'
. Database table tb_test fields:
featureName : TEXT
geometry : POLYGON
4) Code Running on AutoCAD 2015 : OK
In Visual Lisp, I call dbQuery .NET method (file MyCommands.cs):
(setq result_query (dbQuery))
and will return a list:
[0] "FeatureName=first test area , MinX=101.23 , MinY=101.5 , MaxX=215.7 , MaxY=201.953 , Area=5532.771185"
[1] "FeatureName=second test area , MinX=100 , MinY=50 , MaxX=200 , MaxY=100 , Area=5000"
5) P R O B L E M :: Code running on Autocad 2016/2017 ::
Error : "Autodesk application has stopped working"
My plugin run ok on AutoCAD 2014 (.NET 4.0) and AutoCAD 2015 (.NET 4.5), but don't running on AutoCAD 2016/2017.
The code is the same, but changed only AcMgd/AcCoreMgd/AcDbMgd and Target DotNet Framework.
When debug my plugin, crash occurs on
connection.LoadExtension("mod_spatialite");
Then I receive a AutoCAD crash message window, saying:
Autodesk applicaton has stopped working
6) My AutoCAD 2017 plugin code
clique here to download VisualStudio 2013 "AutoCAD2017SpatialiteTest" Solution
MyCommands.cs code
// Test (System.Data.SQLite + SpatialiteSharp) in AutoCAD 2017 plugin
// Date: March, 7, 2017.
//
//==============================================================
using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using System.Data.SQLite;
using SpatialiteSharp;
using System.IO;
using System.Reflection;
// This line is not mandatory, but improves loading performances
[assembly: CommandClass ( typeof ( AutoCAD2017SpatialiteTest.MyCommands ) )]
namespace AutoCAD2017SpatialiteTest
{
// This class is instantiated by AutoCAD for each document when
// a command is called by the user the first time in the context
// of a given document. In other words, non static data in this class
// is implicitly per-document!
public class MyCommands
{
private static readonly object Lock = new object ();
private static bool _haveSetPath;
//*******************************************************************
// LispFunction is similar to CommandMethod but it creates a lisp
// callable function. Many return types are supported not just string
// or integer.
//
//
//
[LispFunction ( "dbQuery", "dbQuery" )]
public ResultBuffer dbQuery ( ResultBuffer args ) // This method can have any name
{
try
{
// Create Spatialite SQL Connection
//
string databaseName = #"c:\temp\dbtest.sqlite";
string connectString = #"Data Source=" + databaseName + ";Version=3;";
SQLiteConnection connection = new SQLiteConnection ( connectString );
/// Open the database and load in the Spatialite extension
connection.Open ();
/// Loads mod_spatialite.dll on the given connection
///
lock ( Lock )
{
//Need to work out where the file is and add it to the path so it can load all the other dlls too
if ( !_haveSetPath )
{
var spatialitePath = Path.Combine ( Path.GetDirectoryName ( Assembly.GetExecutingAssembly ().Location ), (Environment.Is64BitProcess ? "x64" : "x86"), "spatialite" );
Environment.SetEnvironmentVariable ( "PATH", spatialitePath + ";" + Environment.GetEnvironmentVariable ( "PATH" ) );
_haveSetPath = true;
}
}
connection.EnableExtensions ( true );
connection.LoadExtension ( "mod_spatialite" );
// Make some Spatialite function calls
string sql = "SELECT featureName, ST_MINX(geometry), ST_MINY(geometry), ST_MAXX(geometry), ST_MAXY(geometry), ST_AREA(geometry) FROM tb_test ";
double minX = 0.0, minY = 0.0, maxX = 0.0, maxY = 0.0, area = 0.0;
string featureName = "";
string result_query = "";
// initialize resBuf list
//
ResultBuffer resBufCatch = new ResultBuffer ();
resBufCatch.Add ( new TypedValue ( (int)LispDataType.ListBegin ) );
// execute sql query
//
using ( SQLiteCommand command = new SQLiteCommand ( sql, connection ) )
{
using ( SQLiteDataReader reader = command.ExecuteReader () )
{
while ( reader.Read () )
{
featureName = reader.GetString ( 0 );
minX = reader.GetDouble ( 1 );
minY = reader.GetDouble ( 2 );
maxX = reader.GetDouble ( 3 );
maxY = reader.GetDouble ( 4 );
area = reader.GetDouble ( 5 );
// define string with fields values from 'tb_test'
//
result_query = String.Format ( "FeatureName={0} , MinX={1} , MinY={2} , MaxX={3} , MaxY={4} , Area={5}", featureName, minX.ToString (), minY.ToString (), maxX.ToString (), maxY.ToString (), area );
// add result_query to buffer
//
resBufCatch.Add ( new TypedValue ( (int)LispDataType.Text, result_query ) );
}
}
}
// finalize resBuf list
//
resBufCatch.Add ( new TypedValue ( (int)LispDataType.ListEnd ) );
// Close and clean up the database connection
//
connection.Close ();
connection.Dispose ();
// return result_query value to lisp function...
//
return resBufCatch;
}
catch ( System.Exception ex )
{
string exception_message = String.Format ( "Error : {0}", ex.Message );
ResultBuffer resBufCatch = new ResultBuffer ();
resBufCatch.Add ( new TypedValue ( (int)LispDataType.Text, exception_message ) );
return resBufCatch;
}
}
}
}
7) Question
Anybody help me run this AutoCAD2017 plugin?
Thank you very much.
Do you have an error report dialog like this one after the crash?
If yes, don't close the dialog and go to the folder C:\Users\\AppData\Local\Temp (%temp%). There must be a file named dumpdata.zip. In the archive, there is an xml file which can give you more details on the error and a .dmp file you can open in Visual Studio.
I am using cordova-plugin-media-with-compression for an app which runs on IOS and Android. On Android the code is working perfectly, records, play, stop, erase, no problem. On IOS I can play the files saved using the android app, but as soon as I try to record I get error 1 which is MEDIA_ERR_ABORTED (no idea what that means). So works perfectly on Android, but will not record on IOS. I am also using cordovafile for other things and they work, so I know cordova file is working and I verified that I am getting a legitimate folder for the mediapath.
I used the code right out of the example.
$scope.mediapath = cordova.file.externalApplicationStorageDirectory || cordova.file.tempDirectory || cordova.file.sharedDirectory;
$rootScope.mediaOptions = {
SampleRate: 16000,
NumberOfChannels: 1
};
$scope.mediafile = "record-audio.m4a";
$scope.media = new Media($scope.mediapath + $scope.mediafile, function () {
console.log("recordAudio():Audio Success");
},
function (err) { console.log("recordAudio():Audio Error: " + err.code); },
function (s) {
if (s === 4) {
$timeout(function () {
angular.element(document.getElementById('stopButton')).triggerHandler('click');
}, 0);
}
} );
$scope.media.startRecordWithCompression($rootScope.mediaOptions);
Even though . $scope.mediapath = $scope.mediapath.fullPath; worked for a while, I had further errors and ended up with this solution. Note I keep both mediapath and mediapath1 because when using $cordovaFile.readAsDataURL($rootScope.mediapath, $scope.mediafile)... I need the mediapath for ios and android.
$rootScope.mediaOptions = {
SampleRate: 16000,
NumberOfChannels: 1
};
$rootScope.mediapath = cordova.file.tempDirectory || cordova.file.dataDirectory || cordova.file.externalApplicationStorageDirectory || cordova.file.sharedDirectory || cordova.file.applicationStorageDirectory;
$rootScope.mediapath1 = $rootScope.mediapath;
if (cordova.platformId === 'ios') {
$rootScope.mediapath1 = '';
}
then when I need to initialize the media
$scope.mediafile = "audio.m4a";
$scope.media = new Media($rootScope.mediapath1 + $scope.mediafile,
function () {
console.log("recordAudio():Audio Success");
},
function (err) { console.log("recordAudio():Audio Error: " + err.code + err.message); },
function (s) {
// catch change to audio here for example when s===4 the recording has been stopped.
}
});
$scope.media.startRecordWithCompression($rootScope.mediaOptions)
;
I have the latest Notification ANE for iOS at the moment and I have a couple of questions about set up and display of these notifications
When I set up categories is it necessary to set all the parameters that appear in the example to show actions?(or for example we can set up categories without including .setIcon( "ic_stat_distriqt_default" ) for example) This is the code I am using to set up a category:
service.categories.push(
new CategoryBuilder()
.setIdentifier( Constants.REMINDER_CATEGORY )
.addAction(
new ActionBuilder()
.setTitle( "Snooze" )
.setIdentifier( "ACCEPT_IDENTIFIER" )
.build()
)
.addAction(
new ActionBuilder()
.setTitle( "Accept" )
.setDestructive( true )
.setIdentifier( "DELETE_IDENTIFIER" )
.build()
)
.build()
);
One the other hand I am using for now two types of notification, simple and delayed. Simple notification is being displayed normally in notifications box and the event is being dispatched, however delayed notifications is not being displayed in notifications box but event is being dispatched.(Both cases with App open)
Is this the normal behaviour of delayed notification?
Will App dispatch and receive a delayed notification even if it's closed?
Here it's my code for both cases:
//simple notification
public function notifySimple(vo:LocalNotificationVO):void{
if (Notifications.isSupported)
{
_service.notify(
new NotificationBuilder()
.setId( vo.id )
.setAlert( vo.type )
.setTitle( vo.tittle +": "+vo.body)
.setBody( vo.body )
// .setSound( vo.soundPath )
.enableVibration(vo.enableVibration)
.setPayload( vo.payload )
.build()
);
}
}
//Delayed notification
public function setReminderNotification(vo:LocalNotificationVO):void
{
if (Notifications.isSupported)
{
_service.notify(
new NotificationBuilder()
.setId( vo.id )
.setDelay( vo.delay ) // Show the notification 5 seconds in the future
.setRepeatInterval( NotificationRepeatInterval.REPEAT_NONE ) // Repeat the notification every hour
.setAlert( vo.tittle )
.setTitle( vo.body ) //
.setBody( vo.body ) //Body is not displayed
// .setSound( vo.soundPath ) //SOUNDS DISABLED FOR NOW
// .enableVibration(vo.enableVibration)
// .setPayload( vo.payload )
// .setCategory( Constants.REMINDER_CATEGORY )
.build()
);
}
}
Being LocalNotificationVO (With getters that I didn't include):
public function LocalNotificationVO(id:int,
type:String,
tittle:String,
body:String,
payload:String,
delay:int = 0,
enableVibration:Boolean = true,
soundPath:String = "") {
_id = id;
_type = type;
_tittle = tittle;
_body = body;
_payload = payload;
_delay = delay;
_enableVibration = enableVibration;
_soundPath = soundPath;
}
Thank you very much in advance
I use SQlite in a Cordova app built with AngularJS. I bootstrap the app onDeviceReady() and then check if a database and a specific table exist and based on the result do certain things. The app works as expected in Android but in iOS it runs the fist time and then it gets blocked on the white page of the simulator or device! Can anyone give me an insight on how to resolve this issue?
var db = window.sqlitePlugin.openDatabase(
// options
{
name: "users_info.db",
location: 2
},
// success callback
function (msg) {
// console.log("success: " + msg);
// console.log(msg);
},
// error callback
function (msg) {
// console.log("error: " + msg);
}
);
db.transaction(function (tx) {
tx.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name='user'", [], function (tx, result) {
if (result.rows.length == 0) {
console.log('theres no table with this name ');
$scope.$apply(function () {
$location.path('/login');
});
} else {
tx.executeSql(
"select * from user;",
[],
function (tx, res) {
var row = res.rows.item(0);
console.log(row.role);
if (row.role == 4) {
$scope.$apply(function () {
userService.roleid = '4';
userService.userid = row.userid;
$location.path('/student');
});
}
});
console.log('this table exists');
}
});
});
I have also tried the following codes to open the database but again in iOS the app freezes after the first run
var db = $cordovaSQLite.openDB({ name: "users_info.db", location: 1, iosDatabaseLocation: 'default' },
// success callback
function (msg) {
// console.log("success: " + msg);
console.log(msg);
console.log('success');
},
// error callback
function (msg) {
console.log("error: " + msg);
console.log('error');
}
);
I found out that the reason of the issue was that my page containing the code snippet for the SQLite database refreshed twice when loading which caused the codes to read from and write to the SQlite database twice simultaneously which cause the database and consequently the iOS app to freeze. I made sure the codes run only once and it worked like a charm!