Issue with Photo Upload in Enketo after Android 14 / One UI 6.0 Update

Since the Android 14 / One UI 6.0 update (on a Samsung A52 smartphone), the “Photo” type question no longer suggests taking a photo directly; only image selection from the “gallery” is available.
The GUI of the image selection popup has also changed slightly with this update.

In addition to no longer being able to take a photo directly (via Enketo), the photos are incorrectly sent to the server and I can no longer find the photos in my submissions.
I conducted a test by filling out a form with a photo in beginrepeat (6 photos), inserting several photos (already present in my gallery), and then saving it as a draft.
When reloading the draft, the photos are lost.

It seems like there is an issue with loading photos in Enketo (on the front end)?

I will continue to test and provide further feedback.
If you have additional information, I am interested.
For information, Samsung’s “Internet” browser does not seem to present this problem.

Thank you.

Hi @jdugh, welcome back!

Which browsers did you try so far? I would want to test it from my side aswell to provide maximum information to team.

1 Like

Hi @hakan_cetinkaya ,

Indeed, I forgot to specify the browser:
Chrome 125.0.6422.113

I test without a begin repeat, juste 6 simple photos questions. Same error.

I manage “quite easily” to create the bug: a few lost photos.
But I can’t always reproduce the same bug; i.e. always the same lost photos.
Sometimes 5 out of 6 photos are lost.
Sometimes only the last…
Sometimes everything is fine

EDIT :
I found this post on stackoverflow which talks about the camera picker and a “solution” to reactivate it.
But I don’t think this solves the photo loss problem:

@jdugh, did you test this on the KoboCollect Android App or the ODK Collect Android App?

Hi @Kal_Lam ,

This issue only affects Enketo.
Test carried out on the official instance https://eu.kobotoolbox.org/ and on our own Enketo 1.73 instance (a little old :slight_smile: )

Hi @hakan_cetinkaya
I have a StackTrace of my bug :

The affected code :

I will continue other tests on our dev instance.

1 Like

Context and Version Information:

The issue has been observed on the following versions:

  • Device: Samsung A52
  • Android: 14
  • One UI: 6.0
  • Browser: Chrome 125.0.6422.113
  • Enketo Form: Test Form

Problem Description:

In this specific version context, the input type file no longer supports taking photos directly; it only allows image uploads from the gallery. Additionally, sometimes, updating the IndexedDB fails. When this happens, the error is caught here : enketo/packages/enketo-express/public/js/src/module/controller-webform.js at main · enketo/enketo · GitHub

A screenshot of the error is available in my previous post. The generated error occurs when attempting to convert the ‘file’ input to a blob for storage in IndexedDB.

Reproducing the Issue:

To replicate the issue, I perform the following steps:

  1. Control my phone via Chrome on my PC.
  2. Open the Test Form on my phone.
  3. Insert a photo into the first input of the form.
  4. Execute this JavaScript code in the phone’s console:
// A simple function that tries to read the file
function getBase64(file) {
   var reader = new FileReader();
   reader.readAsDataURL(file);
   reader.onload = function () {
     console.log("ok, base64 result: ", reader.result);
   };
   reader.onerror = function (error) {
     console.error('Error: ', error);
   };
}
// Get all input elements (as Enketo does)
fileInputs = [...document.querySelectorAll('form.or input[type="file"], form.or input[type="text"][data-drawing="true"]')];
// Try to read the file from the first input
getBase64(fileInputs[0].files[0]);
// Often it works the first time, but if you try reading multiple times (even with delays):
getBase64(fileInputs[0].files[0]);
// 5 seconds delay...
getBase64(fileInputs[0].files[0]);
...
// At some point, the reader rejects with an error:
DOMException: The requested file could not be read, typically due to permission problems.

Since Enketo reads all file inputs during each _autoSaveRecord to update IndexedDB, this error scenario occurs relatively quickly.

Proposed Temporary Solution:

My initial fix is to replace the files attribute of the input field with a JavaScript File object containing the input file as Blob. This way, the reference to the input file is no longer on the OS (Android), but a blob within the browser, eliminating the file read error.

Here’s the first version of my fix, though not very elegant:
I modified the filepicker widget by injecting a promise allowing the input files to be “switched” with this code:

const self = this;
//...
const reader = new FileReader();
reader.onload = function(e) {
    const blob = new Blob([e.target.result], { type: file.type });
    const dataTransfer = new DataTransfer();
    const newFile = new File([blob], file.name, { type: file.type });
    dataTransfer.items.add(newFile);
    self.element.files = dataTransfer.files;
    resolve();
};
reader.onerror = function (error) {
    input.value = '';
    reject(error);
};
reader.readAsArrayBuffer(file);
// Here, file = event.target.files[0];

This solution worked quite well except in rare cases where a file read error still occurred (Android indicated the file was modified, But when writing this post, I cannot reproduce the error and specify the error code here). In such cases, I cleared the input and used gui.alert to notify the user.

Fixing the Direct Photo Capture Issue:

To address the issue of not being able to take a photo directly from the input, I followed this post and added text/plain to the input’s accept attribute in the filepicker widget:

// At the beginning of init
if (!this.element.getAttribute('accept').includes("text/plain")) {
    this.element.setAttribute('accept', this.element.getAttribute('accept') + ",text/plain");
}

I then modified the switch and resizeFile functions to ensure they worked correctly: enketo/packages/enketo-core/src/widget/file/filepicker.js at main · enketo/enketo · GitHub enketo/packages/enketo-core/src/widget/file/filepicker.js at main · enketo/enketo · GitHub

The camera is now available, along with the gallery!

Conclusion:

Upon writing this post, I removed my initial blob copying fix to capture and document the error trace. Surprisingly, the file access issue no longer occurred without my initial fix. It appears that adding the text/plain accept attribute to the input might fully resolve the file access issue. It’s possible Chrome creates a blob copy when this accept attribute is present or something similar?

To conclude, I plan to submit a issue to the Enketo project to integrate text/plain into the input type file and discuss this with the developers to get their insights.

I hope this message will be complete enough for you to be able to reproduce the bug and understand my search for resolutions

EDIT:
Issue here : Photo/Camera upload on Android 14 · Issue #1321 · enketo/enketo · GitHub