# Odk-x use intent to scan barcode in html page

**URL:** <https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567>\
**Category:** Support\
**Created:** [September 30, 2019, 7:22am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567 "2019-09-30T07:22:50Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![benamor](https://odkx.b-cdn.net/letter_avatar_proxy/v4/letter/b/a587f6/32.png) [@benamor](https://forum.odk-x.org/u/benamor)\
**Post date:** [September 30, 2019, 7:22am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/1 "2019-09-30T07:22:50Z")

</div>

Hello everyone,

I have HTML page like Geotagger where I can Search in the list using input text,  
But I want to make a button where I can use the zxing barcode.  
so I can easily find what I want from the list.  
how can I make Intent in the javascript?  
can anybody help me?

Thanks

---

<div class="post-metadata">

**Author:** ![W\_Brunette](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/w_brunette/32/376_2.png) [@W\_Brunette](https://forum.odk-x.org/u/W_Brunette)\
**Post date:** [September 30, 2019, 8:49pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/2 "2019-09-30T20:49:38Z")

</div>

You can use the odkcommon.js injected interface to launch an intent using the odkCommon.doAction function.

Brief example:

```
    $('#barcode').on('click', function() {
        var dispatchStruct = JSON.stringify({actionTypeKey: actionBarcode,
            htmlPath:htmlFileNameValue, userAction:userActionValue});

        odkCommon.doAction(dispatchStruct, 'com.google.zxing.client.android.SCAN', null);
    });

```

---

<div class="post-metadata">

**Author:** ![benamor](https://odkx.b-cdn.net/letter_avatar_proxy/v4/letter/b/a587f6/32.png) [@benamor](https://forum.odk-x.org/u/benamor)\
**Post date:** [October 7, 2019, 9:29am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/3 "2019-10-07T09:29:02Z")

</div>

hello @W_Brunette  
I did use the odkcommon.js to launch an intent but I can not receive data back .

> window.addEventListener(“load”, function () {  
> odkCommon.registerListener(  
> function () {  
> alert(“inside the listener”);  
> var action = odkCommon.viewFirstQueuedAction();  
> $(“#searchForText”).val(“inside the listener”);  
> if (action !== null) {  
> console.debug(action);  
> $(“#searchForText”).val(JSON.stringify(action));  
> var dispatchStruct = action.dispatchStruct;  
> if (dispatchStruct && dispatchStruct.userAction == “scan-kast-code”) {  
> var jsonValue = action.jsonValue;  
> $(“#searchForText”).val(“status = " + jsonValue.status);  
> if (jsonValue.status === 0) {  
> $(”#searchForText").val(jsonValue.result);  
> console.log(jsonValue);  
> }  
> }  
> // process action – be idempotent!  
> // if processing fails, the action will still  
> // be on the queue.  
> odkCommon.removeFirstQueuedAction();  
> }  
> });  
> $(“#barcode”).click(function () {  
> var dispatchStruct = { userAction: “scan-kast-code” };  
> var intentArgs = {  
> // extras: extrasBundle,  
> // uri: // set the data field of intent to this  
> // data: // unless data is supplied – that takes precedence  
> // type: // set the intent type to this value  
> // package: // set the intent package to this value  
> };
> 
> ```
> return odkCommon.doAction(dispatchStruct,
> 'com.google.zxing.client.android.SCAN',
> intentArgs);
> });
> 
> ```
> 
> })

the registerListener doesn’t work or i don’t know how to use it.

Can you check with me, please.

---

<div class="post-metadata">

**Author:** ![linl33](https://odkx.b-cdn.net/letter_avatar_proxy/v4/letter/l/b487fb/32.png) [@linl33](https://forum.odk-x.org/u/linl33)\
**Post date:** [October 8, 2019, 1:08am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/4 "2019-10-08T01:08:25Z")

</div>

There are a few issues with your listener:

1. `action.dispatchStruct` is a JSON string, you need to parse it to read its content.
2. `action.jsonValue.status` is expected to be -1
3. The result of the scan is stored in `action.jsonValue.result.SCAN_RESULT`

If the issue is that the listener isn’t being called at all, try calling your listener right after registering it.

---

<div class="post-metadata">

**Author:** ![Thien\_Mai](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/thien_mai/32/375_2.png) [@Thien\_Mai](https://forum.odk-x.org/u/Thien_Mai)\
**Post date:** [August 11, 2020, 9:40am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/5 "2020-08-11T09:40:36Z")

</div>

Hi @W_Brunette @linl33,

I am getting the same issue. This code worked correctly with old ODK, but it does not work with ODK-X as the listener never get called:

> ```
> let saveBarcodeFromScan = () => {
> let value = odkCommon.viewFirstQueuedAction();
> console.log("saveBarcodeFromScan: " + value);
> if ( value !== null && value !== undefined ) {
> let action = JSON.parse(value);
> let dispatch = JSON.parse(action.dispatchStruct);
> if (dispatch.userAction === 'barcodeScan' && action.jsonValue.status === -1) {
> let barcode = action.jsonValue.result.SCAN_RESULT;
> callback(barcode);
> odkCommon.removeFirstQueuedAction();
> }
> }
> };
> odkCommon.registerListener(saveBarcodeFromScan);
> odkCommon.doAction(JSON.stringify({ userAction: 'barcodeScan' }), 'com.google.zxing.client.android.SCAN', null);
> 
> ```

Calling the listener right after registration also does not help:

> odkCommon.registerListener(saveBarcodeFromScan);  
> saveBarcodeFromScan(); // immediately call the listener  
> odkCommon.doAction(JSON.stringify({ userAction: ‘barcodeScan’ }), ‘com.google.zxing.client.android.SCAN’, null);

This is a blocker for me as barcode scanner is one of my production key feature.

---

<div class="post-metadata">

**Author:** ![Emil](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/emil/32/3_2.png) [@Emil](https://forum.odk-x.org/u/Emil)\
**Post date:** [August 11, 2020, 11:58am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/6 "2020-08-11T11:58:16Z")

</div>

Hello,  
Are you just trying to get the value of the scan?  
If so, I believe something like this can do it?

1. Create a function to handle the call back and give a name to your userAction (in this example we’ll call it “thatsScanny”) like e.g.

```javascript
function javaChange() {
    var action = odkCommon.viewFirstQueuedAction();
    if ( action !== null ) {
        console.log("call back called");
        if (action.dispatchStruct.userAction == "thatsScanny") {
            odkCommon.removeFirstQueuedAction();
            if (action.jsonValue.result && action.jsonValue.result.SCAN_RESULT) {
                var scanRes = action.jsonValue.result.SCAN_RESULT;
                // call you function to handle the code.. e.g doSearch()
                doSearch(scanRes); 
            }
        }
    }
}

```

1. Hook it up in the pages initialization method,e.g.

```plaintext
function display() { // we will call this onLoad
    console.log("Setting up display");
    odkCommon.registerListener( javaChange );
    javaChange(); // invoke it once, just because...

   // Assuming you have a button with id = btnScan
    $("#btnScan").on("click", function() {
        var dispatchStruct = {userAction: 'thatsScanny'};
        var x = odkSurvey.scanBarcode(dispatchStruct);
        console.log(x);
    })

}

```

best regards,  
/emil

---

<div class="post-metadata">

**Author:** ![Thien\_Mai](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/thien_mai/32/375_2.png) [@Thien\_Mai](https://forum.odk-x.org/u/Thien_Mai)\
**Post date:** [August 11, 2020, 12:24pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/7 "2020-08-11T12:24:49Z")

</div>

Thanks for your quick reply, @Emil. It seems that your suggestion is very similar to my code. I cannot see the difference and why my code does not work. The problem is the registered listener never get called after `odkCommonIf.doAction()` is finished.

---

<div class="post-metadata">

**Author:** ![Emil](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/emil/32/3_2.png) [@Emil](https://forum.odk-x.org/u/Emil)\
**Post date:** [August 11, 2020, 12:29pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/8 "2020-08-11T12:29:28Z")

</div>

I think a main difference, is that I use the odkSurvey.scanBarcode() method instead of calling odkCommenIf.doAction()

```javascript
odkSurvey.scanBarcode(dispatchStruct);

```

Also; I need to invoke it once on page load for some reason:

```javascript
javaChange(); // invoke it once, just because...

```

---

<div class="post-metadata">

**Author:** ![Thien\_Mai](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/thien_mai/32/375_2.png) [@Thien\_Mai](https://forum.odk-x.org/u/Thien_Mai)\
**Post date:** [August 11, 2020, 12:56pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/9 "2020-08-11T12:56:53Z")

</div>

Hi Emil, could you point me to documentation of odkSurvey.scanBarcode() method.

---

<div class="post-metadata">

**Author:** ![Emil](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/emil/32/3_2.png) [@Emil](https://forum.odk-x.org/u/Emil)\
**Post date:** [August 11, 2020, 1:24pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/10 "2020-08-11T13:24:09Z")

</div>

Hmmm… that’s indeed a very good question 😆  
I looked at the source:

> <https://github.com/odk-x/app-designer/blob/master/app/system/survey/js/odkSurvey.js>

---

<div class="post-metadata">

**Author:** ![Thien\_Mai](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/thien_mai/32/375_2.png) [@Thien\_Mai](https://forum.odk-x.org/u/Thien_Mai)\
**Post date:** [August 14, 2020, 9:53am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/11 "2020-08-14T09:53:42Z")

</div>

Hi @Emil,

It does not work for me as odkSurvey.js in turn also calls OdkCommon.doAction().  
I tried debugging ODK Table app with Android Studio and found why the listener never gets called. I will list my findings in another topic.

Anyway, I could make it work with a workaround. Thanks for following up.

---

<div class="post-metadata">

**Author:** ![W\_Brunette](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/w_brunette/32/376_2.png) [@W\_Brunette](https://forum.odk-x.org/u/W_Brunette)\
**Post date:** [August 15, 2020, 8:47pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/12 "2020-08-15T20:47:23Z")

</div>

@Thien_Mai please let us know what you find so we can fix it.

---

<div class="post-metadata">

**Author:** ![Thien\_Mai](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/thien_mai/32/375_2.png) [@Thien\_Mai](https://forum.odk-x.org/u/Thien_Mai)\
**Post date:** [August 17, 2020, 6:32am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/13 "2020-08-17T06:32:02Z")

</div>

@W_Brunette, please correct me if I am wrong. As my understanding, once `doAction()` is finished, the Android app will call this method in `ODKWebView` to signal its client to call the registered listener:  
`ODKWebView.class`:

```
public void signalQueuedActionAvailable() {
        this.log.i("ODKWebView", "[" + this.hashCode() + "] signalQueuedActionAvailable()");
        this.loadJavascriptUrl("javascript:window.odkCommon.signalQueuedActionAvailable()", true);
        this.shouldReloadAfterLoad = true;
    }

```

Let’s take a look at implementation of `loadJavascriptUrl()`:

```
private synchronized void loadJavascriptUrl(final String javascriptUrl, boolean suppressIfFrameworkIsNotLoaded) {
        if (!this.isInactive()) {
            if (this.isLoadPageFrameworkFinished || !suppressIfFrameworkIsNotLoaded) {
                this.log.i("ODKWebView", "[" + this.hashCode() + "] loadJavascriptUrl: IMMEDIATE: " + javascriptUrl);
                if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
                    this.post(new Runnable() {
                        public void run() {
                            ODKWebView.this.loadUrl(javascriptUrl);
                        }
                    });
                } else {
                    this.loadUrl(javascriptUrl);
                }
            }
        }
    }

```

`this.isLoadPageFrameworkFinished` is controlling whether the WebView should sends signal to client.

The problem I have found is: Once the barcode scanner app is launched, the current view is paused which then set `this.isLoadPageFrameworkFinished` to _false_. However, it is never set back to _true_ then (e.g after the barcode scanner app exits and the view is resumed)

```
public void onPause() {
        ...
        this.isLoadPageFrameworkFinished = false;
    }

```

That’s what I have observed through app debugging. Any thoughts?

---

<div class="post-metadata">

**Author:** ![Emil](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/emil/32/3_2.png) [@Emil](https://forum.odk-x.org/u/Emil)\
**Post date:** [August 17, 2020, 7:30am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/14 "2020-08-17T07:30:17Z")

</div>

That looks like a good finding! Perhaps that could also explain why I need to call javaChange(); once before scanning works?

> [@Emil](#):
>
> Also; I need to invoke it once on page load for some reason:
> 
> ```auto
> javaChange(); // invoke it once, just because...
> 
> ```

---

<div class="post-metadata">

**Author:** ![Thien\_Mai](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/thien_mai/32/375_2.png) [@Thien\_Mai](https://forum.odk-x.org/u/Thien_Mai)\
**Post date:** [August 17, 2020, 7:59am UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/15 "2020-08-17T07:59:00Z")

</div>

@Emil It does not work for me and I do not really understand why it works for you. As my understanding, when ODK Table cannot send signal for its client to fetch the result of `doAction()` (your `javaChange()` call), the result will then be retained in `guardedQueuedActions` list in ODK Table. Your next call of `javaChange()` will actually fetch that result and remove the result from the ODK. That means, nth call of listener will fetch result of (n-1)th `doAction()`?

---

<div class="post-metadata">

**Author:** ![W\_Brunette](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/w_brunette/32/376_2.png) [@W\_Brunette](https://forum.odk-x.org/u/W_Brunette)\
**Post date:** [August 24, 2020, 10:18pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/16 "2020-08-24T22:18:23Z")

</div>

@Thien_Mai here is some code I pulled from one of our projects that calls the barcode scanner and returns the barcode inside Tables.

Hopefully this will help. Let us know if you have direct questions about the code snippet. I think I copied enough.

```
/* action added to button */
 $('#barcode').on('click', doActionZxing);

/* code */
var actionBarcode = 0;
var htmlFileNameValue = "delivery_start";
var userActionValue = "launchBarcode";

util.actionTypeKey = 'actionTypeKey'

function doActionZxing() {
    var dispatchStruct = JSON.stringify({
        [util.actionTypeKey]: actionBarcode,
        htmlPath: htmlFileNameValue,
        userAction: userActionValue
    });

    odkCommon.doAction(dispatchStruct, 'com.google.zxing.client.android.SCAN', null);
}

function callBackFn () {
    var action = odkCommon.viewFirstQueuedAction();
    console.log('callback entered with action: ' + action);

    if (action === null || action === undefined) {
        // The queue is empty
        return;
    }

    var dispatchStr = JSON.parse(action.dispatchStruct);
    if (dispatchStr === null || dispatchStr === undefined) {
        console.log('Error: missing dispatch struct');
        odkCommon.removeFirstQueuedAction();
        return;
    }

    var actionType = dispatchStr[util.actionTypeKey];
    console.log('callBackFn: actionType: ' + actionType);

    if (actionType === actionBarcode) {
        handleBarcodeCallback(action, dispatchStr);
    } else {
        handleCallback(action, dispatchStr);
    }

    odkCommon.removeFirstQueuedAction();
}

```

---

<div class="post-metadata">

**Author:** ![shey\_kerkup](https://odkx.b-cdn.net/user_avatar/forum.odk-x.org/shey_kerkup/32/970_2.png) [@shey\_kerkup](https://forum.odk-x.org/u/shey_kerkup)\
**Post date:** [October 31, 2021, 1:01pm UTC](https://forum.odk-x.org/t/odk-x-use-intent-to-scan-barcode-in-html-page/567/17 "2021-10-31T13:01:24Z")

</div>

Hi, this might be coming a bit late but I noticed you registered the listener and called it immediately even before calling the `odkCommon.doAction`. The goal is to register the listener on page load and call it immediately after registering it because when the button to scan is clicked, control leaves the app and it is later returned to the activity that launched the intent - reason why it is good to register the listener and call it at once on page load.

I ran into this post because I faced similar issues. 😀
