/** Manages the connection to the service. */privatefinalServiceConnectionmServiceConnection=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamecomponentName,IBinderiBinder){// We must use this to expose the service methods.mPrintService=IDirectPrintService.Stub.asInterface(iBinder);Log.d("PrintConnection","Print service connected.");}@OverridepublicvoidonServiceDisconnected(ComponentNamecomponentName){Log.d("PrintConnection","Print service disconnected.");mPrintService=null;}};/** Binds to the direct print service by dynamically locating it in the system. */privatestaticbooleanbindToDirectPrintService(Contextcontext,ServiceConnectionserviceConnection){IntentdirectPrintImplicitIntent=newIntent("com.verifone.intent.action.DIRECT_PRINT");directPrintImplicitIntent.addCategory("com.verifone.intent.category.DIRECT_PRINT");IntentdirectPrintIntent=createExplicitFromImplicitIntent(context,directPrintImplicitIntent);returndirectPrintIntent!=null&&context.bindService(directPrintIntent,serviceConnection,Context.BIND_AUTO_CREATE);}/** Used when binding to the print service to turn a dynamic intent into an explicit intent. */@NullableprivatestaticIntentcreateExplicitFromImplicitIntent(Contextcontext,IntentimplicitIntent){//Retrieve all services that can match the given intentPackageManagerpm=context.getPackageManager();List<ResolveInfo>resolveInfo=pm.queryIntentServices(implicitIntent,0);//Make sure only one match was foundif(resolveInfo==null||resolveInfo.size()!=1){Log.e(TAG,"Could not find service for intent with action "+implicitIntent.getAction()+".");returnnull;}//Get component info and create ComponentNameResolveInfoserviceInfo=resolveInfo.get(0);StringpackageName=serviceInfo.serviceInfo.packageName;StringclassName=serviceInfo.serviceInfo.name;ComponentNamecomponent=newComponentName(packageName,className);//Create a new intent. Use the old one for extras and such reuseIntentexplicitIntent=newIntent(implicitIntent);//Set the component to be explicitexplicitIntent.setComponent(component);returnexplicitIntent;}
/** Manages the connection to the service. */privatevalmServiceConnection=object:ServiceConnection{overridefunonServiceConnected(componentName:ComponentName,iBinder:IBinder){// We must use this to expose the service methods.mPrintService=IDirectPrintService.Stub.asInterface(iBinder)Log.d("PrintConnection","Print service connected.")}overridefunonServiceDisconnected(componentName:ComponentName){Log.d("PrintConnection","Print service disconnected.")mPrintService=null}}/** Binds to the direct print service by dynamically locating it in the system. */privatefunbindToDirectPrintService(context:Context,serviceConnection:ServiceConnection):Boolean{valdirectPrintImplicitIntent=Intent("com.verifone.intent.action.DIRECT_PRINT")directPrintImplicitIntent.addCategory("com.verifone.intent.category.DIRECT_PRINT")valdirectPrintIntent=createExplicitFromImplicitIntent(context,directPrintImplicitIntent)returndirectPrintIntent!=null&&context.bindService(directPrintIntent,serviceConnection,Context.BIND_AUTO_CREATE)}/** Used when binding to the print service to turn a dynamic intent into an explicit intent. */@NullableprivatefuncreateExplicitFromImplicitIntent(context:Context,implicitIntent:Intent):Intent? {//Retrieve all services that can match the given intentvalpm=context.getPackageManager()valresolveInfo=pm.queryIntentServices(implicitIntent,0)//Make sure only one match was foundif(resolveInfo==null||resolveInfo!!.size!=1){Log.e(TAG,"Could not find service for intent with action "+implicitIntent.action+".")returnnull}//Get component info and create ComponentNamevalserviceInfo=resolveInfo!!.get(0)valpackageName=serviceInfo.serviceInfo.packageNamevalclassName=serviceInfo.serviceInfo.namevalcomponent=ComponentName(packageName,className)//Create a new intent. Use the old one for extras and such reusevalexplicitIntent=Intent(implicitIntent)//Set the component to be explicitexplicitIntent.component=componentreturnexplicitIntent}
1
/** Manages the connection to the service. */
1
/** Manages the connection to the service. */
Here’s a sample print listener that receives back the different events for printing.
/** * The listener which receives the callbacks from the print service for print job status * updates. */privatefinalIDirectPrintListenermPrintListener=newIDirectPrintListener.Stub(){/** Called when a print job has moved from the queue and is being processed. */@Overridepublicvoidstarted(StringprintId)throwsRemoteException{}/** Called when the print job cannot continue, but could be resumed later. */@Overridepublicvoidblock(StringprintId,StringerrorMessage)throwsRemoteException{}/** Called when the print job has finished being cancelled. This is the final message. */@Overridepublicvoidcancel(StringprintId)throwsRemoteException{}/** Called when the print job has failed, and cannot be resumed. This is the final message. */@Overridepublicvoidfailed(StringprintId,StringerrorMessage)throwsRemoteException{}/** Called when the print job is complete. */@Overridepublicvoidcomplete(StringprintId)throwsRemoteException{}};
/*** The listener which receives the callbacks from the print service for print job status* updates.*/privatevalmPrintListener=object:IDirectPrintListener.Stub(){/** Called when a print job has moved from the queue and is being processed. */@Throws(RemoteException::class)funstarted(printId:String){}/** Called when the print job cannot continue, but could be resumed later. */@Throws(RemoteException::class)funblock(printId:String,errorMessage:String){}/** Called when the print job has finished being cancelled. This is the final message. */@Throws(RemoteException::class)funcancel(printId:String){}/** Called when the print job has failed, and cannot be resumed. This is the final message. */@Throws(RemoteException::class)funfailed(printId:String,errorMessage:String){}/** Called when the print job is complete. */@Throws(RemoteException::class)funcomplete(printId:String){}}
/** * The listener which receives the callbacks from the print service for print job status * updates. */
/** * The listener which receives the callbacks from the print service for print job status * updates. */
An example of printing a receipt once the service is bound and the listener is set up.
Barcode scanning APIs are available for scanning if the BYOD device has a Camera.
To setup the scanner first add a listener PaymentSdk.initScanListener(scannerListener)
to receive the scan results. Then the scanning can be started using PaymentSdk.startBarcodeScanner(attributes).
There are a few attributes like scan formats, display feed, scan area, front/rear camera etc that you can pass to the API.
The scan formats are listed under the ScannerBarcodeFormatEnum enumeration.
For Android the attributes must contain an Activity or Fragment under the ScannerConfiguration.ATTRIBUTE_DISPLAY_FEED_PARENT key to work.
The listener that was setup will receive the results as they are scanned.
private val mScannerListener = ScannerListener { status, attributes ->
var barcode: String? = ""
var barcodeType: String? = ""
if (status === STATUS_BARCODE_DETECTED) {
if (attributes.containsKey(ATTRIBUTE_BARCODE)) {
barcode = attributes[ATTRIBUTE_BARCODE] as String?
}
if (attributes.containsKey(ATTRIBUTE_BARCODE_FORMAT)) {
barcodeType = attributes[ATTRIBUTE_BARCODE_FORMAT] as String?
}
Log.d(TAG, "Scanner status:$status$barcode-$barcodeType")
} else {
Log.d(TAG, "Scanner status:$status")
}
}
fun initScanner() {
mPsdk.initScanListener(mScannerListener)
val attributes: HashMap<String, Any> = HashMap()
// Display the scanner at 90% of display view
val metrics = resources.displayMetrics
val rect = Rect(
(metrics.widthPixels.toFloat() * .1f).toInt(),
(metrics.heightPixels.toFloat() * .1f).toInt(),
(metrics.widthPixels.toFloat() * .9f).toInt(),
(metrics.heightPixels.toFloat() * .9f).toInt()
)
attributes[ScannerConfiguration.ATTRIBUTE_SCAN_AREA_LIMIT] = rect
attributes[ScannerConfiguration.ATTRIBUTE_SET_DIRECTION] = 2
attributes[ScannerConfiguration.ATTRIBUTE_ACTIVATE_LIGHT] = false
attributes[ScannerConfiguration.ATTRIBUTE_PLAY_SOUND] = true
attributes[ScannerConfiguration.ATTRIBUTE_DISPLAY_FEED_PARENT] = this
// Optionally limit the barcode formats. Leaving this empty
// will search for the default list of barcodes.
val scanFormats = arrayOf(
ScannerBarcodeFormatEnum.UPCA,
ScannerBarcodeFormatEnum.UPCE,
ScannerBarcodeFormatEnum.QRCODE
)
attributes[ScannerConfiguration.ATTRIBUTE_SCANNING_FORMATS] = scanFormats
mPsdk.startBarcodeScanner(attributes)
}
Following dependencies need to be added to the application’s build.gradle.
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.google.zxing:core:3.4.0'
implementation 'androidx.preference:preference-ktx:1.1.1'
//scanner optionsvarconfig=[String:Any]()config[VFIScannerConfigurationATTRIBUTEPLAYSOUND]=trueconfig[VFIScannerConfigurationATTRIBUTEACTIVATELIGHT]=trueconfig[VFIScannerConfigurationATTRIBUTECONTINUOUSSCAN]=trueconfig[VFIScannerConfigurationATTRIBUTESETDIRECTION]=Int(2)//psdk scanner interfacesdk.initiateScan(view:scanWindowView,config:config,completion:{(result,error)iniflete=error{switche{case.Cancel://user has cancelled, therefore exit the scanner modecase.Exit://if the continuous scan was false, an exit will be called after scanning itemdefault:// handle the error case here}return}guardletdata=resultelse{// handle nil resultreturn}// handle the data})