I am developing an inventory management app in xamarin forms using Zebra TC20 model. Right now I am able to retrieve barcode data using datawedge. Now I am trying to disable and enable barcode scanner using datawedge as well. I have surfed and found out we can broadcast to datawedge for enable and disable the barcode scanner. Now I am having the issue when I want to enable or disable the the scanner from a page I am retrieving an error message Java.Lang.NullPointerException: 'Attempt to invoke virtual method 'void android.content.Context.sendBroadcast(android.content.Intent)' on a null object reference
. The scanner functions are implemented in Android file. I am using dependency service to call the scanner functions. I have attached the code I have done.
MainActivity.cs
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IKeyboardListener, IScannerConnection
{
private static string ACTION_DATAWEDGE_FROM_6_2 = "com.symbol.datawedge.api.ACTION";
private static string EXTRA_CREATE_PROFILE = "com.symbol.datawedge.api.CREATE_PROFILE";
private static string EXTRA_SET_CONFIG = "com.symbol.datawedge.api.SET_CONFIG";
private static string EXTRA_PROFILE_NAME = "Barcode Scan";
private DataWedgeReceiver _broadcastReceiver = null;
protected override void OnCreate(Bundle bundle)
{
base.Window.RequestFeature(WindowFeatures.ActionBar);
// Name of the MainActivity theme you had there before.
// Or you can use global::Android.Resource.Style.ThemeHoloLight
base.SetTheme(Resource.Style.MainTheme);
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
DependencyService.Register<ToastNotification>(); // Register your dependency
ToastNotification.Init(this);
var container = new SimpleContainer(); // Create a SimpleCOntainer
container.Register<IGeolocator, Geolocator>(); // Register the Geolocator
container.Register<IDevice>(t => AndroidDevice.CurrentDevice); // Register the Device
Resolver.ResetResolver(); // Reset the resolver
Resolver.SetResolver(container.GetResolver()); // Resolve it
FFImageLoading.Forms.Platform.CachedImageRenderer.Init(enableFastRenderer: true);
UserDialogs.Init(this);
Rg.Plugins.Popup.Popup.Init(this, bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
global::ZXing.Net.Mobile.Forms.Android.Platform.Init();
_broadcastReceiver = new DataWedgeReceiver();
App inventoryApp = new App(OnSaveSignature);
_broadcastReceiver.scanDataReceived += (s, scanData) =>
{
MessagingCenter.Send<App, string>(inventoryApp, "ScanBarcode", scanData);
};
CreateProfile();
//DependencyService.Register<ToastNotification>();
//ToastNotification.Init(this, new PlatformOptions() { SmallIconDrawable = Android.Resource.Drawable.IcDialogInfo });
LoadApplication(inventoryApp);
}
public override void OnBackPressed()
{
if (Rg.Plugins.Popup.Popup.SendBackPressed(base.OnBackPressed))
{
// Do something if there are some pages in the `PopupStack`
}
else
{
// Do something if there are not any pages in the `PopupStack`
}
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
// check if the current item id
// is equals to the back button id
if (item.ItemId == 16908332 && !RFIDStockCountViewModel.IsPosted && RFIDStockCountViewModel.IsStockCounting)
{
return false;
/*
if (Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.Count > 0)
{
//LIFO is the only game in town! - so send back the last page
int index = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.Count - 1;
var currPage = (CustomContentPage)Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack[index];
// check if the page has subscribed to
// the custom back button event
if (currPage?.CustomBackButtonAction != null)
{
// invoke the Custom back button action
currPage?.CustomBackButtonAction.Invoke();
// and disable the default back button action
return false;
}
}
// if its not subscribed then go ahead
// with the default back button action
return base.OnOptionsItemSelected(item);
*/
}
else
{
// since its not the back button
//click, pass the event to the base
return base.OnOptionsItemSelected(item);
}
}
private async Task<bool> OnSaveSignature(Stream bitmap, string filename)
{
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
var file = Path.Combine(path, "signature.png");
using (var dest = File.OpenWrite(file))
{
await bitmap.CopyToAsync(dest);
}
return true;
}
//public override void OnBackPressed()
//{
// if (Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.Count > 0)
// {
// //LIFO is the only game in town! - so send back the last page
// int index = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.Count - 1;
// var currentpage = (CustomContentPage)Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack[index];
// // check if the page has subscribed to
// // the custom back button event
// if (currentpage?.CustomBackButtonAction != null)
// {
// currentpage?.CustomBackButtonAction.Invoke();
// }
// else
// {
// base.OnBackPressed();
// }
// }
//}
public override bool OnKeyDown(Keycode keyCode, KeyEvent e)
{
if (e.KeyCode.GetHashCode() == 139 || e.KeyCode.GetHashCode() == 280)
{
MessagingCenter.Send<IKeyboardListener, string>(this, "KeyboardListener", "TRUE");
}
return base.OnKeyDown(keyCode, e);
}
public override bool OnKeyUp(Keycode keyCode, KeyEvent e)
{
if (e.KeyCode.GetHashCode() == 139 || e.KeyCode.GetHashCode() == 280)
{
MessagingCenter.Send<IKeyboardListener, string>(this, "KeyboardListener", "FALSE");
}
return base.OnKeyDown(keyCode, e);
}
protected override void OnResume()
{
base.OnResume();
if (null != _broadcastReceiver)
{
// Register the broadcast receiver
IntentFilter filter = new IntentFilter(DataWedgeReceiver.IntentAction);
filter.AddCategory(DataWedgeReceiver.IntentCategory);
Android.App.Application.Context.RegisterReceiver(_broadcastReceiver, filter);
}
}
protected override void OnPause()
{
if (null != _broadcastReceiver)
{
// Unregister the broadcast receiver
Android.App.Application.Context.UnregisterReceiver(_broadcastReceiver);
}
base.OnStop();
}
private void CreateProfile()
{
String profileName = EXTRA_PROFILE_NAME;
SendDataWedgeIntentWithExtra(ACTION_DATAWEDGE_FROM_6_2, EXTRA_CREATE_PROFILE, profileName);
// Now configure that created profile to apply to our application
Bundle profileConfig = new Bundle();
profileConfig.PutString("PROFILE_NAME", EXTRA_PROFILE_NAME);
profileConfig.PutString("PROFILE_ENABLED", "true"); // Seems these are all strings
profileConfig.PutString("CONFIG_MODE", "CREATE_IF_NOT_EXIST");
Bundle barcodeConfig = new Bundle();
barcodeConfig.PutString("PLUGIN_NAME", "BARCODE");
//barcodeConfig.PutString("RESET_CONFIG", "true"); // This is the default but never hurts to specify
Bundle barcodeProps = new Bundle();
barcodeProps.PutString("scanner_input_enabled", "true"); // This is the default but never hurts to specify
barcodeProps.PutString("scanner_selection_by_identifier", "AUTO ");
barcodeProps.PutString("scanner_selection", "auto ");
barcodeProps.PutString("aim_mode", "off ");
barcodeProps.PutString("illumination_mode", "off ");
barcodeConfig.PutBundle("PARAM_LIST", barcodeProps);
profileConfig.PutBundle("PLUGIN_CONFIG", barcodeConfig);
Bundle appConfig = new Bundle();
appConfig.PutString("PACKAGE_NAME", this.PackageName); // Associate the profile with this app
appConfig.PutStringArray("ACTIVITY_LIST", new String[] { "*" });
profileConfig.PutParcelableArray("APP_LIST", new Bundle[] { appConfig });
SendDataWedgeIntentWithExtra(ACTION_DATAWEDGE_FROM_6_2, EXTRA_SET_CONFIG, profileConfig);
// You can only configure one plugin at a time, we have done the barcode input, now do the intent output
profileConfig.Remove("PLUGIN_CONFIG");
Bundle intentConfig = new Bundle();
intentConfig.PutString("PLUGIN_NAME", "INTENT");
intentConfig.PutString("RESET_CONFIG", "true");
Bundle intentProps = new Bundle();
intentProps.PutString("intent_output_enabled", "true");
intentProps.PutString("intent_action", DataWedgeReceiver.IntentAction);
intentProps.PutString("intent_delivery", "2");
intentConfig.PutBundle("PARAM_LIST", intentProps);
profileConfig.PutBundle("PLUGIN_CONFIG", intentConfig);
SendDataWedgeIntentWithExtra(ACTION_DATAWEDGE_FROM_6_2, EXTRA_SET_CONFIG, profileConfig);
}
private void SendDataWedgeIntentWithExtra(String action, String extraKey, Bundle extras)
{
Intent dwIntent = new Intent();
dwIntent.SetAction(action);
dwIntent.PutExtra(extraKey, extras);
SendBroadcast(dwIntent);
}
private void SendDataWedgeIntentWithExtra(String action, String extraKey, String extraValue)
{
Intent dwIntent = new Intent();
dwIntent.SetAction(action);
dwIntent.PutExtra(extraKey, extraValue);
SendBroadcast(dwIntent);
}
public void SendScannerEnable()
{
SendDataWedgeIntentWithExtra(ACTION_DATAWEDGE_FROM_6_2, EXTRA_SET_CONFIG, "ENABLE_PLUGIN");
}
public void SendScannerDisable()
{
SendDataWedgeIntentWithExtra(ACTION_DATAWEDGE_FROM_6_2, EXTRA_SET_CONFIG, "DISABLE_PLUGIN");
}
}
}
Snip from Page.cs
protected override void OnAppearing()
{
DependencyService.Get<IScannerConnection>().SendScannerEnable();
MessagingCenter.Subscribe<App, string>(this, "ScanBarcode", (sender, arg) =>
{
ScanBarcode(arg);
});
base.OnAppearing();
}
I have searched through internet but I didn't get any resource on how to fix it.
Thank you.
The url below helped me to fix my problem. I had to create a new scanner class which enables and disables datawedge profile by triggering events. https://developer.zebra.com/community/home/blog/2018/07/11/xamarinforms-freshmvvm-datawedge-take-2