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

File Size coming as 0 in android 11 #314

Open
3 tasks done
giteshpatil opened this issue Sep 27, 2021 · 6 comments
Open
3 tasks done

File Size coming as 0 in android 11 #314

giteshpatil opened this issue Sep 27, 2021 · 6 comments

Comments

@giteshpatil
Copy link

giteshpatil commented Sep 27, 2021

Bug Report

On Android below 11 works fine and size also comes perfect but on android 11 size always comes as 0

Problem

What is expected to happen?

It should record the file and should be able to show file size more than 0

What does actually happen?

Not working in android 11

Information

Any more information needed please feel free to ask.

Command or Code

recordAudio(){
let extension ='wav' // 'm4a' 'mp3'

this.file.createFile(this.file.dataDirectory, '111file.'+extension, true).then(() => {
this.myFile = this.media.create(this.file.dataDirectory+'111file.'+extension,);
console.log('filepath',this.file.dataDirectory+'111file.'+extension)
console.log("this.myFile",this.myFile)
this.myFile.startRecord();
alert('started recording')
}).catch(err=>{
console.log('createFile err',err)
});

async stopRecording(){
let extension = 'wav'// 'm4a' 'mp3'
alert('stop called')
this.myFile.stopRecord()

setTimeout(() => {
let duration = this.myFile.getDuration();
console.log(duration);
console.log("this.myFile2",this.myFile)

this.file.readAsDataURL(this.file.dataDirectory, '111file.'+extension).then(res=>{
console.log("checkFile res",res)
let url = this.file.dataDirectory+'111file.'+extension
this.file.resolveLocalFilesystemUrl(url).then(fileEntry => {
fileEntry.getMetadata((metadata) => {
console.log("size",metadata.size);//metadata.size is the size in bytes
})
})
}).catch(err=>{
console.log("checkFile err",err)
})
}, 1000);
}

Environment, Platform, Device

Device used: Oneplus 9R
OS: Android 11

Version information

Project based on ionic 3
cordova 10.0.0
ionic 5.4.13
"cordova-plugin-file": "^6.0.2",
"cordova-android": "8.1.0",
"@ionic-native/media": "^4.20.0",
"cordova-plugin-media": "^5.0.3",
"typescript": "2.8.4"

Checklist

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

I've got this too.

I believe it's related to changes to Android's new filesystem permissions in 11.
https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage

See this long thread over at apache/cordova-plugin-file#426 for some info on how other plugins are battling it out:

I haven't found a solution yet but I'll add some info here if I find anything. Others have been juggling the API version to work around it but that's no longer an option for those publishing to Google Play.

Here's relevant logging info from adb logcat that may be of use to the plugin maintainers. The main errors seem to be:

MediaProvider: java.lang.IllegalArgumentException: Primary directory null not allowed for content://media/external_primary/file; allowed directories are [Download, Documents]

and

System.err: java.io.FileNotFoundException: /storage/emulated/0/tmprecording-1633411896974.3gp: open failed: EPERM (Operation not permitted)

Here's the full log:

MediaRecorder: Constructor MediaRecorder
MediaRecorderJNI: setup
StagefrightRecorder: property set(service.camera.rec.running, 0) result = 0
MediaPlayerService: Create new media recorder client from pid 27788
RestrictionPolicy: userId: 0, isMicrophoneEnabledAsUser : true
MediaRecorderJNI: setAudioSource(1)
MediaRecorderJNI: setAudioEncoder(3)
RestrictionPolicy: userId: 0, isMicrophoneEnabledAsUser : true
RestrictionPolicy: userId: 0 isAudioRecordAllowed : true
MediaProvider: insertFileIfNecessary failed
MediaProvider: java.lang.IllegalArgumentException: Primary directory null not allowed for content://media/external_primary/file; allowed directories are [Download, Documents]
MediaProvider: 	at com.android.providers.media.MediaProvider.ensureFileColumns(MediaProvider.java:2932)
MediaProvider: 	at com.android.providers.media.MediaProvider.ensureUniqueFileColumns(MediaProvider.java:2597)
MediaProvider: 	at com.android.providers.media.MediaProvider.insertFile(MediaProvider.java:3291)
MediaProvider: 	at com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:3844)
MediaProvider: 	at com.android.providers.media.MediaProvider.insert(MediaProvider.java:3555)
MediaProvider: 	at com.android.providers.media.MediaProvider.insertFileForFuse(MediaProvider.java:7199)
MediaProvider: 	at com.android.providers.media.MediaProvider.insertFileIfNecessaryForFuse(MediaProvider.java:7293)
System.err: java.io.FileNotFoundException: /storage/emulated/0/tmprecording-1633411896974.3gp: open failed: EPERM (Operation not permitted)
System.err: 	at libcore.io.IoBridge.open(IoBridge.java:492)
System.err: 	at java.io.RandomAccessFile.<init>(RandomAccessFile.java:289)
System.err: 	at java.io.RandomAccessFile.<init>(RandomAccessFile.java:152)
System.err: 	at android.media.MediaRecorder.prepare(MediaRecorder.java:1417)
System.err: 	at org.apache.cordova.media.AudioPlayer.startRecording(AudioPlayer.java:161)
System.err: 	at org.apache.cordova.media.AudioHandler.startRecordingAudio(AudioHandler.java:287)
System.err: 	at org.apache.cordova.media.AudioHandler.promptForRecord(AudioHandler.java:543)
System.err: 	at org.apache.cordova.media.AudioHandler.execute(AudioHandler.java:118)
System.err: 	at org.apache.cordova.CordovaPlugin.execute(CordovaPlugin.java:98)
System.err: 	at org.apache.cordova.PluginManager.exec(PluginManager.java:139)
System.err: 	at org.apache.cordova.CordovaBridge.jsExec(CordovaBridge.java:59)
System.err: 	at org.apache.cordova.engine.SystemExposedJsApi.exec(SystemExposedJsApi.java:41)
System.err: 	at android.os.MessageQueue.nativePollOnce(Native Method)
System.err: 	at android.os.MessageQueue.next(MessageQueue.java:335)
System.err: 	at android.os.Looper.loop(Looper.java:206)
System.err: 	at android.os.HandlerThread.run(HandlerThread.java:67)
System.err: Caused by: android.system.ErrnoException: open failed: EPERM (Operation not permitted)
System.err: 	at libcore.io.Linux.open(Native Method)
System.err: 	at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
System.err: 	at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
System.err: 	at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
System.err: 	at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8448)
System.err: 	at libcore.io.IoBridge.open(IoBridge.java:478)
System.err: 	... 15 more
PluginManager: THREAD WARNING: exec() call to Media.startRecordingAudio blocked the main thread for 35ms. Plugin should use CordovaInterface.getThreadPool().
chromium: [INFO:CONSOLE(406)] "recordAudio():Audio Error [object Object]", source: http://localhost:8080/app.js (406)

@breautek
Copy link

breautek commented Oct 5, 2021

Thanks for the investigation @sc0ttdav3y

This matches my findings, the external root directory /storage/emulated/0/ (or it may be a /sdcard path if your device has a real external storage) is no longer writable starting in API 29/30. API offered an escape hatch, but today you must target API 30.

The problematic line is

tempFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording-" + System.currentTimeMillis() + ".3gp";

If external media is mounted (which virtually all phones have external media due to emulation, hence the /storage/emulated name), it will attempt to write to it's root directory.

Personally, I'm not sure on the original rationale. We should never write to an external medium unless explicitly requested.

@sc0ttdav3y
Copy link

I've got a local working solution for Android 11, and linked a draft PR for your review:
#316

I don't have the capacity to test this across lots of devices and OSs, so I can't check all the PR boxes.

@spinybeast
Copy link

any updates of this? have same problem

@rozpuszczalny
Copy link

rozpuszczalny commented Dec 2, 2021

Looks like it's fixed by #317. Personally, I've installed cordova-plugin-media directly from GitHub by doing this: npm i --save apache/cordova-plugin-media#4093f7e (4093f7e is the latest commit so far on master branch)

@kenfouo
Copy link

kenfouo commented Apr 27, 2022

the solution that worked for me: since API 30 Android has restrictions on access to external storage.

install file plugin : cordova plugin add cordova-plugin-file

var onSuccess = function (e) {
console.log('onSuccess', e);
};
var onError = function (e) {
console.log('onError', e);
};

window.resolveLocalFileSystemURL(cordova.file.dataDirectory,function (directory)
{
var my_media = new Media(directory+'recording.mp3', onSuccess, onError )
}, err =>{
console.log('resolveLocalFileSystemURL ', JSON.stringify(err));
} );

and it works for me !!!!!

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

No branches or pull requests

6 participants