Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
0 Kudos

Timing is everything and various reasons meant I never got past a small demo of QR codes in SAP. However as I have just watched a video with some guys with QR codes on their T-shirts at Teched, I thought I would share my little QR code adventure and hope to see some business case examples using QR codes. As I am no Java developer please bear with me and take the contents as my beginner's tale and please point out any obvious issues. So how hard can it be for me as a beginner in Java to generate a QR code and get scanned data into SAP.

Where I live, I see QR codes all the time and I have wanted to integrate them into SAP. I like the idea of a "quick response" of data into a mobile device as I hate typing on mobile phones. I will cover  technical demonstrations of using QR codes in SAP. The solution requires a SAP system with a java stack to generate the  QR codes. The QR codes can be generated and used in any web application or custom ABAP transaction. No need to rely on external web sites to generate the codes.

I have already blogged about QR codes (which are part of an open source barcode application) in smartforms and sapscript here  (Barcodes in SAP with the Barcode Writer in Pure Postscript.), but this is for transaction use.

If you are still unsure about QR codes, then try the wikipedia [link | http://en.wikipedia.org/wiki/QR_Code]

Or download [The Weather Channel Android App from TV! | http://www.youtube.com/watch?v=N3e3WwoW9LQ]

During my Google searching, I found

) a Zebra crossing to do the actual QR code generation, [ZXing (Zebra Crossing) | http://code.google.com/p/zxing/] (later versions now exist than the one I use). To get started I used the code I found here. I adapted the code so I could generate the image online. </p><p>) the custom ABAP code is based on SAP program "SAPHTML_DEMO1"

The purpose of the ABAP transaction is to map the location of any customer/contact and provide a "quick response" of the map url to a mobile phone via the QR code. I made some attempts to use [vCard | http://en.wikipedia.org/wiki/VCard] and [MEcard | http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/addressbo...] formats to send contact details via QR codes. However from my experience the actual applications that scan QR codes vary widely in their adoption of formats for contact information. I will attempt to show how maybe contact details can be passed from a QRcode to an online form later in the blog.

<u>ZXing (Zebra Crossing)</u>

So first things first we need the QR code and to get it I made a journey into the world of Java/JSP/servlets and the SAP Java engine from a developers point of view. 

To get to my Zebra Crossing I had to use an Ant. So after a trip to [Apache Ant | http://ant.apache.org/]  I trusted the binary installation. Using Ant I managed to build the key component of ZXing "core" I needed. The getting started section at the ZXing website is [here | http://code.google.com/p/zxing/wiki/GettingStarted]. Within the ZXing "core" component is the base QR code used to generate the QR code in for my ABAP transaction. ZXing has many options/sections and platforms but all I needed was the core component to generate the QR code as I was not going to decode/scan anything.

Now as I am not a developer I needed some clues in how to use my newly acquired core.jar file. Now searching the web provided so many options that it took some time to actually get to a working version.

<u>Java images: JSP vs Servlet</u><br /><br />Now I had for a long time a working version based purely in JSP. There are many examples, on the web, where the image is done via pure JSP. Now this works, however in the SAP java engine a warning message about output streams is generated in the error logs. So checking further into the information available and the way forward was to split the actual image generation into a servlet which is called by the JSP. The way I found to do this split came from note 1218520.<br /><br />With the SAP Netweaver Developer Studio I built the following into an application.<br /><br />To get started with the NWDS I used one of my favourite SDN [blogs. | Single Sign On to BSP pages from Duet's Action Pane] A lot of Holger Bruchelt's blogs have been really useful to me in other areas of SAP and maybe I will cover some of the things I did with SPNEGO elsewhere. However any mistakes or wrong steps with the process are mine. For this application I did not follow any of the authorisation steps for single sign on (so I skipped anything to do with authorisation/security of the blog link). This service is just a demo and therefore allows anonymous access to the JSP/Servlet if no authorisations are input. </p><p>NWDS versions, we have a 640 system so I have a 640 based NWDS. So any of the following screen shots just show the general options and you need to check the settings on your NWDS version. </p><p><u>JSP </u></p><div><div><pre class="jive-pre"><textarea cols="70" rows="5"><%@ page language="java" %>

<%response.sendRedirect( "/QRplutus/servlet/QRimg?" + request.getQueryString());

%>

</textarea><br /><br /></pre><u>Servlet</u></div><div>Servlets are not covered in the blog link above so I created a servlet with DoGet options and added the following code.</div><div><textarea cols="70" rows="15">package servlet;

import java.io.IOException;

import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.google.zxing.*;

import com.google.zxing.common.ByteMatrix;

import com.google.zxing.qrcode.QRCodeWriter;

public class QRimg extends HttpServlet {

protected void doGet(

HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

String pw = request.getParameter ("w");

String ph = request.getParameter ("h");

  int width;

int height;

if ( pw == null ) {

width = 200;

}

else

{

width = Integer.parseInt(pw);

}

if ( ph == null ) {

height = 200;

}

else

{

height = Integer.parseInt(ph);

}

String text =request.getParameter ("t");

if ( text == null ) {

text = "**ERROR No text passed to encode";

}

QRCodeWriter writer = new QRCodeWriter();

ByteMatrix matrix = null;

try {

matrix = writer.encode(text, BarcodeFormat.QR_CODE, width, height);

} catch (WriterException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

byte[][] matrixByte = matrix.getArray();

BufferedImage bimg = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);

byte[] linearbuffer = new byte[width*height];

int i=0;

for(int y=0;y<height;y++)

for(int x=0;x<width;x++)

linearbuffer[i++]=matrixByte[y][x];

bimg.getRaster().setDataElements(0, 0, width, height, linearbuffer);

response.setContentType("image/jpeg");

ImageIO.write(bimg, "jpeg", response.getOutputStream());

}

}

</textarea> <br /><u>ZXing Core.jar</u></div><div>The external jar core.jar needs to be added to the project. I tested 1.4 and the 1.5 (shown below) versions.</div><div>!https://weblogs.sdn.sap.com/weblogs/images/251909024/corejar.JPG|height=484|alt=core.jar|width=600|s...!</div><div><u>Thanks NWDS!</u>

Thanks to the NWDS I was able to create the above code as it kindly highlighted unnecessary and missing imports and it added the error exception (which needs further development!).

<u>A context root of a problem</u>

From my previous experience with SPNEGO I new, thanks to the forums and this post   (how to run the servlet  from nwds) that I needed to update application.xml.http://hostname:5xx00/QRplutus/QRcode.jsp?t=testQRcode&w=300&h=300<br /><br /><br />Obviously hostname is the hostname of the SAP server<br />5xx00 should match the instance number of the SAP java engine, e.g. 50000<br />t= is the text to encode<br />w= and h= control the height and width of the QR code.<br /><br /><br />You can find the whole SAP [EAR file here | http://bit.ly/sapzxing], to see the contents, it uses ZXing version 1.4.</p><p><br /><u>A URL hack to find a place on a map</u> </p><p>So as we do not have any geocoding functions on or 640/NW04 based system I needed someway of finding a customer based on the information available.</p><p>After a visit to Mapki   (http://mapki.com/wiki/Google_Map_Parameters)I used the customer name and postcode as part of the google maps url (q=customername&near=country,postcode).

I created a table HTML containing a google map and QR code of the same URL. Seen below is the ABAP transaction based on SAPHTML_DEMO1 and the QR code scanned and URL followed on the phone.

<u>Scanning Contact Details from a QRcode to a SAP server.</u>

I have always read that one of the uses of QRcodes is with Business Cards and contact details. I have never come across a business card with a QR code apart from online demos. So not a great start for any demo, however I did learn more about SAP in the process of putting it together. 

So my intention with the following is that someone has a QRcode with his/her contact details and the event/situation means that these details can be entered directly into SAP via a scanning application.

The ZXing code contains a barcode scanning application that I have installed on my Android phone. I am about to show a bit of a hack of the contents of the barcode scanning application but it is the use of QR codes I want to explore. I do not intend that this is an acceptable use of the ZXing application. As this is a blog, I cover my attempts in the order I went through them to achieve the goal. (The way forward with ZXing would be scanning with Intents which is covered later, from my beginners point of view :smile:

As mentioned previously Vcards and MEcards formats can be found for QR code encoding. Depending on the contents of the QR code then the Android ZXing barcode scanning application can offer fixed options for further processing.

Within the scanning application there is the option to add a custom search URL as shown

*I apologise for the quality of the screen shots, a product from Apple allows you to take screen shots for free by holding down 2 buttons. With my Andriod based phone I have an upcoming choice to either "root" my phone or install the Andriod SDK which will allow free screen shots. So I am sticking with the current quality screen shots for the time being :(</p><p>So with a custom url "search" entered. I generated a QRcode with pure text with a ~ separator. E.g. robert~russell. Now once I scanned this into the barcode scanner on my phone the "custom search" button was available.</p><p>_Modify the old Retro BSP ECTECHED code._</p><p>The URL shown above contains a %s for the text from the scanned barcode. The SAP backend BSP is for creating a flight customer.</p><p>So using my ~ separated text QRcode,  I modified the BSP to accept the text and split it into first name and last name for the BSP application. Shown below. So after scanning the QR code I hit the custom search icon and the BSP had filled out the form with the text. This is just a demo but obviously with a lot more effort more I could try and take it further. </p><p>!https://weblogs.sdn.sap.com/weblogs/images/251909024/sapbspform.jpg|height=290|alt=BSP form with the text coming from a QR code|width=607|src=https://weblogs.sdn.sap.com/weblogs/images/251909024/sapbspform.jpg|border=0!</p><p>So in summary I like QR codes, although from my point of view I would like to see some standards in how scanning applications deal with contents of the QR codes (2d barcodes). I have tried many barcode scanning applications and they all vary from offering to add contact details or just plain text and it can be frustrating dealing with anything other than URL encoded 2d barcodes.</p><p>I was going to stop here, however the screen shot issue brought me back....... </p><p>_A full Android SDK installed for screenshots for my phone_</p><p>Ok so to get a better screen shot I did follow a guide on the web that was titled "How to install Android SDK (and take screenshots)....". </p><p>So running DDMS program in the SDK I was able to grab the screens and a bit of image magick  (http://www.imagemagick.org/script/index.php) to combine the images here. </p><p>!https://weblogs.sdn.sap.com/weblogs/images/251909024/zxing75.jpg|height=429|alt=Android SDK enabled screen shot|width=245|src=https://weblogs.sdn.sap.com/weblogs/images/251909024/zxing75.jpg!</p><p> </p><p>_Scanning with Intent_*

Ok so I made the choice to get the full SDK for screenshots! I felt I had to take it one step further so I took a trip to the ZXing site to check out Android Intents here.  (http://code.google.com/p/zxing/wiki/ScanningViaIntent)

The ZXing license question page indicates "no license issues" with scanning by intents, however check the[ license page here yourself | http://code.google.com/p/zxing/wiki/LicenseQuestions]. 

Scanning with intents allows you to access the results of the barcode scanning application. So you can skip learning all its source code, just what I wanted! Therefore I could get a MEcard formatted results directly to the URL of my BSP.

So I have my first ever mobile app on my own phone based on scanning intent which is followed by another intent to the default browser. On selecting the application the barcode scanner is started and I scan a MEcard formatted QRcode and the results are sent to the BSP via a URL call with the scanned contents. Again I have modified examples and left all that error checking out! I would obviously suggest this code is not a starting point for further development however it is below only for reference.

package com.example.test;import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;public class qr2sap extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);     Intent intent = new Intent("com.google.zxing.client.android.SCAN");     intent.putExtra("SCAN_MODE", "QR_CODE_MODE");     startActivityForResult(intent, 0); }public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 0) {     if (resultCode == RESULT_OK) {         String contents = intent.getStringExtra("SCAN_RESULT");         intent = new Intent(Intent.ACTION_VIEW);                Uri data = Uri.parse("http://{F.Q.D.N}:8001/sap/bc/bsp/sap/zand/mecard.html?t=" + contents );                           intent.setData(data);         startActivity(intent );             } else if (resultCode == RESULT_CANCELED) {         // Handle cancel     } }}} 

The results on the BSP look like this. I have not gone through and formatted the Mecard information,as my intention was to get data to SAP from the barcode scanner. So this time I added another page to the BSP and split the line at the first colon in the MEcard data.

 !https://weblogs.sdn.sap.com/weblogs/images/251909024/mecard2bsp700.jpg|height=300|alt=BSP with MEcard |width=500|src=https://weblogs.sdn.sap.com/weblogs/images/251909024/mecard2bsp700.jpg!</body>

1 Comment