Capacitor: bug: Camera cannot select picture from Redmi Gallery app

Created on 16 Oct 2019  路  16Comments  路  Source: ionic-team/capacitor

Bug Report

Capacitor Version

npx cap doctor output:
Installed Dependencies:
@capacitor/ios not installed
@capacitor/core 1.2.1
@capacitor/cli 1.2.1
@capacitor/android 1.2.1

Affected Platform(s)

  • [x] Android
  • [ ] iOS
  • [ ] Electron
  • [ ] Web

Current Behavior

Using the Camera plugin on Android Redmi phones, when a picture is selected in the Gallery app, this error is thrown: Unable to process image. It doesn't manifest itself with other apps (e.g. File Manager) and also there was no problem with the Cordova plugin which we used before upgrading to Capacitor.

Expected Behavior


Users are able to use the default Gallery app to select their pictures on Redmi phones.

Sample Code or Sample Application Repo

This is the config we use:
const options: CameraOptions = { quality: 30, resultType: CameraResultType.Uri, allowEditing: false, source: CameraSource.Photos, };

Reproduction Steps

Configure the Camera plugin to return a Uri and use the option to select a picture from gallery instead of taking a new photo.

Other Technical Details

  • Phone: Redmi 6A/Redmi Note 7
  • Android version: 8.1/9
  • MIUI version: 10.3.6/10.3.6

Other Information

I suspect the bug concerns other MIUI devices, such as Xiaomi phones. I managed to track down the problem to saveTemporaryImage method in Camera.java. contentUri.getlastPathSegment tries to select the filename and a copy of the file is created in the cacheDir.

However, contentUri from the Gallery app has this format:
content://com.miui.gallery.open/raw/%2Fstorage%2Femulated%2F0%2FDCIM%2FCamera%2FIMG_20191013_191506.jpg

while the other apps return unescaped slashes in the path, e.g.
content://com.mi.android.globalFileexplorer.myprovider/external_files/DCIM/Camera/IMG_20191013_191506.jpg

I created an easy solution for our app (using a random filename) but this is probably a symptom of a more serious issue and I don't know what the proper fix would be. Is it enough to just unescape the path?

bug android low

Most helpful comment

As no one from the Capacitor team has replied, I'll at least give you a workaround.

  1. Created a file called named patch-camera.js in the project root folder with this content:
const fs = require("fs");
const f =
  "node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java";

fs.readFile(f, "utf8", function(err, data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(
    "String filename = contentUri.getLastPathSegment()",
    'String filename = "file"'
  );

  fs.writeFile(f, result, "utf8", function(err) {
    if (err) return console.log(err);
  });
});

As you can see, this fix is very fragile as it relies on the specific node_modules path and Java source code. This ensures that a timestamp is used for the file name instead of the broken name from the Gallery app.

  1. Add the postinstall script to your package.json to patch the Capacitor source code.
 "scripts": {
    "build": "ng build --prod && npx cap sync",
    "postinstall": "node patch-camera.js"

This automatically runs the fix after npm install and works perfectly with @capacitor/android": "^1.2.1". We haven't updated to 1.3 yet.

All 16 comments

I got the same problem with you.

The same problem I'm facing

As no one from the Capacitor team has replied, I'll at least give you a workaround.

  1. Created a file called named patch-camera.js in the project root folder with this content:
const fs = require("fs");
const f =
  "node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java";

fs.readFile(f, "utf8", function(err, data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(
    "String filename = contentUri.getLastPathSegment()",
    'String filename = "file"'
  );

  fs.writeFile(f, result, "utf8", function(err) {
    if (err) return console.log(err);
  });
});

As you can see, this fix is very fragile as it relies on the specific node_modules path and Java source code. This ensures that a timestamp is used for the file name instead of the broken name from the Gallery app.

  1. Add the postinstall script to your package.json to patch the Capacitor source code.
 "scripts": {
    "build": "ng build --prod && npx cap sync",
    "postinstall": "node patch-camera.js"

This automatically runs the fix after npm install and works perfectly with @capacitor/android": "^1.2.1". We haven't updated to 1.3 yet.

do you know if it's possible to install the miui gallery in a not xiaomi device?
I've tried in different apps and they work fine.

I haven't tried to install the APK manually but the app doesn't seem to be available at the Play Store. The problem is this Gallery is the default one for Xiaomi/Redmi users and while the hack is simple, it's not a long-term solution as we have to check the source code with each release to make sure it doesn't break.

We ran into this issue immediately after migrating from Cordova but hoped it would be fixed quickly.

Hello, I am facing this same problem with xiaomi. Our business really needs the camera and our customers are complaining. I think I will try this workaround, but is there any prediction of a definitive solution?

As no one from the Capacitor team has replied, I'll at least give you a workaround.

  1. Created a file called named patch-camera.js in the project root folder with this content:
const fs = require("fs");
const f =
  "node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java";

fs.readFile(f, "utf8", function(err, data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(
    "String filename = contentUri.getLastPathSegment()",
    'String filename = "file"'
  );

  fs.writeFile(f, result, "utf8", function(err) {
    if (err) return console.log(err);
  });
});

As you can see, this fix is very fragile as it relies on the specific node_modules path and Java source code. This ensures that a timestamp is used for the file name instead of the broken name from the Gallery app.

  1. Add the postinstall script to your package.json to patch the Capacitor source code.
 "scripts": {
    "build": "ng build --prod && npx cap sync",
    "postinstall": "node patch-camera.js"

This automatically runs the fix after npm install and works perfectly with @capacitor/android": "^1.2.1". We haven't updated to 1.3 yet.

This worked for me, hope we could get "not patched" solution soon :)

I can confirm the same issue. Picking an image via the default Xiaomi gallery app results in a "Unable to process image" error. Other gallery apps seem to work, but its a blocker for us since most people with xiaomi devices use the default gallery app.

The patched version and the old cordova plugin work for now

same issue on Xiaomi gallery

I acknowledge the exactly same issue on my Xiaomi phone while selecting photo from the gallery. Here is my adb log.

07-23 17:08:25.212 29040 29040 D Capacitor: Sending plugin error: {"save":false,"callbackId":"49711431","pluginId":"Camera","methodName":"getPhoto","success":false,"error":{"message":"Unable to process image"}}
07-23 17:08:25.215 29040 29040 D Capacitor: App restarted
07-23 17:08:25.216 29040 29040 D Capacitor: App started
07-23 17:08:25.218 29040 29040 D Capacitor/App: Firing change: true

As no one from the Capacitor team has replied, I'll at least give you a workaround.

  1. Created a file called named patch-camera.js in the project root folder with this content:
const fs = require("fs");
const f =
  "node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java";

fs.readFile(f, "utf8", function(err, data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(
    "String filename = contentUri.getLastPathSegment()",
    'String filename = "file"'
  );

  fs.writeFile(f, result, "utf8", function(err) {
    if (err) return console.log(err);
  });
});

As you can see, this fix is very fragile as it relies on the specific node_modules path and Java source code. This ensures that a timestamp is used for the file name instead of the broken name from the Gallery app.

  1. Add the postinstall script to your package.json to patch the Capacitor source code.
 "scripts": {
    "build": "ng build --prod && npx cap sync",
    "postinstall": "node patch-camera.js"

This automatically runs the fix after npm install and works perfectly with @capacitor/android": "^1.2.1". We haven't updated to 1.3 yet.

This fix is working for me, thanks.

I also have the same problem, when I upload a file from the gallery (the default xiaomi application) it doesn't work, but when I use the default Google Photos app it works

Note: the device that I use redmi note 8

capacitorcam
It fixes also this? cannot run cam on my phone when deploying a capacitor ionic app :S

same issue on Xiaomi gallery

same issue

As no one from the Capacitor team has replied, I'll at least give you a workaround.

  1. Created a file called named patch-camera.js in the project root folder with this content:
const fs = require("fs");
const f =
  "node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java";

fs.readFile(f, "utf8", function(err, data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(
    "String filename = contentUri.getLastPathSegment()",
    'String filename = "file"'
  );

  fs.writeFile(f, result, "utf8", function(err) {
    if (err) return console.log(err);
  });
});

As you can see, this fix is very fragile as it relies on the specific node_modules path and Java source code. This ensures that a timestamp is used for the file name instead of the broken name from the Gallery app.

  1. Add the postinstall script to your package.json to patch the Capacitor source code.
 "scripts": {
    "build": "ng build --prod && npx cap sync",
    "postinstall": "node patch-camera.js"

This automatically runs the fix after npm install and works perfectly with @capacitor/android": "^1.2.1". We haven't updated to 1.3 yet.

Works!!! Thanks @jirifranc 馃槃

Was this page helpful?
0 / 5 - 0 ratings