Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cordova-plugin-media-capture video not working android 13 #286

Open
3 tasks done
CaiqueNds opened this issue Oct 19, 2023 · 7 comments
Open
3 tasks done

cordova-plugin-media-capture video not working android 13 #286

CaiqueNds opened this issue Oct 19, 2023 · 7 comments
Labels
Milestone

Comments

@CaiqueNds
Copy link

Bug Report

cordova-plugin-media-capture video not working android 13

Problem

In new versions of Android 13, it is not possible to move video files to the application directory, as the plugin is returning videos from the path file:///storage/emulated/0/DCIM/Camera/

What is expected to happen?

The returned path is expected to be:
file:///data/user/0/myapp/cache/

What does actually happen?

the path returned by the plugin
file:///storage/emulated/0/DCIM/Camera/

Information

use an android 13 and make a video. Check whether it will be stored in the dcim folder or in the application cache
android bug sample:
MicrosoftTeams-image

Command or Code

you need to use the cordova-media-capture plugin and make a video
and check that the video path is correct

Environment, Platform, Device

android 13
Samsung

Version information

cordova-android 12.0.0
ionic 4
android

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@breautek
Copy link

In new versions of Android 13, it is not possible to move video files to the application directory, as the plugin is returning videos from the path file:///storage/emulated/0/DCIM/Camera/

To be clear, under scoped storage rules (which is effective since API 29) you wouldn't be able to move, but you should be able to copy it using the file plugin.

Files recorded will be owned by the camera app rather than your own app, therefore all write operations via the filesystem is restricted which would include the move operation.

v5 of this plugin should already request the READ_MEDIA_VIDEO permission so that the recorded video can be read.

The plugin storing at /storage/emulated/0/DCIM/Camera/ is nothing new, in fact it's not the plugin that decides this location by the underlying camera app.

@CaiqueNds
Copy link
Author

I can't copy files from dcim to my directory within the app in this specific case even if I try to copy the file instead of moving it using cordova-plugin-file

This error appears to me:
image

This error is being presented in newer Android 13 versions with Samsung. Other versions such as Xiaomi or Google Pixel do not occur. Or even older Android 13 with Samsung

sample
video file path:
image
application file path:
image

@breautek
Copy link

INVALID_MODIFICATION_ERR should only be thrown if you're attempting to modify the file I believe..

Can you share the code that produces this error?

@CaiqueNds
Copy link
Author

CaiqueNds commented Oct 20, 2023

This is where the error occurs and I capture the video from media capture and pass it to the plugin file:

async criaEstruturaDiretoriosCopiaArquivo(
    new_path: string,
    path_file: string,
    file_name: string,
    gerar_nome_random: boolean = true
  ): Promise<string> {
    let new_path_file = '';
    //This is where I set the path where the file will be saved
    await this.criaCaminhoDiretorio(new_path).then((x) => {
      new_path_file = x;
    });

    const new_file_name = !gerar_nome_random
      ? file_name
      : (Math.floor(Math.random() * (10000 - 1 + 1)) + 1).toString() +
        "." +
        file_name.slice(file_name.lastIndexOf(".") + 1); 
    return this.file
      .copyFile(path_file, file_name, new_path_file, new_file_name)
      .then(() => {
        return new_path + "/" + new_file_name;
      })
      .catch((err) => {
        console.error(err);
        return "";
      });
  }`

@breautek breautek added the bug label Oct 20, 2023
@breautek
Copy link

Thanks for your co-operation, it's helping me understand the full picture.

based on the provided code, this does appear to be a bug...

On the topic of changing the default path, we were experimenting with PR #277 though I believe that PR only changed the audio recording directory to the app's internal cache directory.

I think the plugin as it stands now gets a content url which it resolves to a file url which gets passed to the webview. Perhaps we can learn from that PoC PR and use the content resolver and get the input stream so that plugin can copy the content using the media store api to the app's cache directory then it can return the file url to the cache directory instead. There is a performance concern if you're copying a large video file... but it will be necessary if we want to use the file plugin to access the file I think.

The plugin I don't think exposes the content url, but if it did, then a media store plugin could be used to do file manipulation operations as well. This could allow us to avoid copying the file unless explicitly desired by the developer... as an alternate solution...

@CaiqueNds
Copy link
Author

I partially solved it by taking this file, generating a blob of it and using the file plugin to record it within my app

@CaiqueNds
Copy link
Author

my solution was. Instead of copying or moving the file received by the video plugin from the device's camera folder. It was creating a blob of this file and writing this blob directly to the desired path..

async workAroundBugGravacaoVideo(
    path_file,
    file_name,
    new_path_file,
    new_file_name
  ) {
    const destinationDirectoryEntry = await this.file.resolveDirectoryUrl(
      new_path_file
    );
    const originDirectoryEntry = await this.file.resolveDirectoryUrl(path_file);
    const fileEntry = await this.file.getFile(originDirectoryEntry, file_name, {
      create: false,
    });

    return this.saveBinaryFile(
      fileEntry,
      destinationDirectoryEntry,
      new_file_name
    );
  }
 saveBinaryFile(fileEntry, dirEntry, fileName) {
    return new Promise((resolve, reject) => {
      fileEntry.file(function (file) {
        var reader = new FileReader();
        reader.readAsArrayBuffer(file);
        dirEntry.getFile(
          fileName,
          { create: true, exclusive: false },
          function (fileEntry) {
            fileEntry.createWriter(function (fileWriter) {
              fileWriter.onwriteend = function () {
                resolve(null);
              };
              fileWriter.onerror = function (e) {
                console.log("Failed file write: " + e.toString());
                reject();
              };
              fileWriter.write(file);
            });
          }
        );
      });
    });
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants