I am building a Xamarin.Android application for a Zebra TC-70 Android device. My main activity runs the scanner just fine the first time through. It gets the data from the scanner and then passes data to another activity just fine. If I cancel the new activity or complete my work and return to the first activity, the scanner does not re-initialize. Here is my code:
[Activity(Label = "MyApp", MainLauncher = true, Icon = "@mipmap/icon",
ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : AppCompatActivity, EMDKManager.IEMDKListener
{
//EMDK
private BarcodeManager _barcodeManager;
private EMDKManager _emdkManager;
private EditText _scanBarcodeEditText;
private Scanner _scanner;
void EMDKManager.IEMDKListener.OnClosed()
{
if(_emdkManager != null)
{
_emdkManager.Release();
_emdkManager = null;
}
}
void EMDKManager.IEMDKListener.OnOpened(EMDKManager p0)
{
_emdkManager = p0;
InitScanner();
}
protected override void OnResume()
{
base.OnResume();
var intent = new Intent(this, typeof(FpmsDataService));
BindService(intent, _dataServiceConnection, Bind.AutoCreate);
_scanBarcodeEditText.Text = string.Empty;
InitScanner();
}
protected override void OnPause()
{
base.OnPause();
UnbindService(_dataServiceConnection);
DeinitScanner();
if (_emdkManager != null)
{
_emdkManager.Release();
_emdkManager = null;
}
}
protected override void OnDestroy()
{
base.OnDestroy();
DeinitScanner();
if(_emdkManager != null)
{
_emdkManager.Release();
_emdkManager = null;
}
Log.Information("Destroyed FirePMS MainActivity");
Log.CloseAndFlush();
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Window.SetFlags(WindowManagerFlags.KeepScreenOn, WindowManagerFlags.KeepScreenOn);
SetContentView(Resource.Layout.Main);
_scanBarcodeEditText = FindViewById<EditText>(Resource.Id.MaintenanceScanBarcode_EditText);
//Initialize Scanner
var results = EMDKManager.GetEMDKManager(Application.Context, this);
}
private void InitScanner()
{
if(_emdkManager != null)
{
if(_barcodeManager == null)
{
try
{
//Get the feature object such as BarcodeManager object for accessing the feature.
_barcodeManager = (BarcodeManager)_emdkManager.GetInstance(EMDKManager.FEATURE_TYPE.Barcode);
_scanner = _barcodeManager.GetDevice(BarcodeManager.DeviceIdentifier.Default);
if (_scanner != null)
{
//Attach the Data Event handler to get the data callbacks.
_scanner.Data += Scanner_Data;
_scanner.Status += Scanner_Status;
_scanner.Enable();
}
else
{
Log.Error("Failed to enable scanner");
}
}
catch (ScannerException e)
{
Log.Error(e.Message);
}
catch (Exception ex)
{
Log.Error(ex.Message);
}
}
}
}
private void Scanner_Status(object sender, Scanner.StatusEventArgs e)
{
var state = e.P0.State;
if(state == StatusData.ScannerStates.Idle)
{
try
{
if (_scanner.IsEnabled &&
!_scanner.IsReadPending)
{
SetScannerConfig();
_scanner.Read();
}
}
catch (ScannerException e1)
{
Log.Error(e1.Message);
}
}
}
private void DeinitScanner()
{
if(_emdkManager != null)
{
if(_scanner != null)
{
try
{
_scanner.CancelRead();
_scanner.Disable();
_scanner.Data -= Scanner_Data;
_scanner.Status -= Scanner_Status;
_scanner.Release();
}
catch (ScannerException e)
{
Log.Error(e.Result.Description);
}
}
}
if (_barcodeManager != null)
{
_emdkManager.Release(EMDKManager.FEATURE_TYPE.Barcode);
}
_barcodeManager = null;
_scanner = null;
}
private void SetScannerConfig()
{
var config = _scanner.GetConfig();
config.SkipOnUnsupported = ScannerConfig.SkipOnUnSupported.None;
config.ScanParams.DecodeLEDFeedback = true;
config.ReaderParams.ReaderSpecific.ImagerSpecific.PicklistEx = ScannerConfig.PicklistEx.Hardware;
config.DecoderParams.Code39.Enabled = true;
config.DecoderParams.Code128.Enabled = false;
_scanner.SetConfig(config);
}
private void Scanner_Data(object sender, Scanner.DataEventArgs e)
{
var scanDataCollection = e.P0;
if((scanDataCollection != null) && (scanDataCollection.Result == ScannerResults.Success))
{
var scanData = scanDataCollection.GetScanData();
if (scanData[0].Data == null)
{
return;
}
RunOnUiThread(() => _scanBarcodeEditText.Text = scanData[0].Data);
RunOnUiThread(ProcessScan);
}
}
private void ProcessScan()
{
if (string.IsNullOrEmpty(_scanBarcodeEditText.Text))
{
Toast.MakeText(this, "You must scan or enter a barcode to begin", ToastLength.Long).Show();
return;
}
else
{
var intent = new Intent(this, typeof(SecondActivity));
intent.PutExtra("ScannedData",_scanBarcodeEditText.Text);
StartActivity(intent)
}
}
}
Any suggestions would be greatly appreciated. As I indicated, the process works just fine the first time, it's when I return to this activity that the scanner is no longer initialized and doesn't come back.
I suspect the EMDK is not being properly released before the activity is restarted. If you take a look at the following article, though using Java the principle is the same and the advice there is to release the EMDK in onStop(). See the note about managing the EMDK instance about half way down.