hyochan / react-native-audio-recorder-player

react-native native module for audio recorder and player.
MIT License
707 stars 212 forks source link

Sound recorder issue of read and write of external storage in Android 13 #548

Open abduldeveloper opened 1 year ago

abduldeveloper commented 1 year ago

Version of react-native-audio-recorder-player 3.5.1

Version of React Native 0.68.5

Platforms you faced the error (IOS or Android or both?) Android

Expected behavior Audio recording without forced access and current play store are need to change the buildToolsVersion = "33.0.0" compileSdkVersion = 33 targetSdkVersion = 33

Actual behavior Due to the change of storage access in Android 13, it is not possible to record audio

After many search about the permissions and reading the Android documents and reading the source of this library, I realized that this library does not actually work on Android 12 and 13. According to this document, WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE permissions do not exist in Android 13, and READ_MEDIA_AUDIO is available instead. Storage permissions are also always shown as never_ask_again . If WRITE_EXTERNAL_STORAGE is necessary in this library, and if this permission is not granted, the promise will be rejected. Please check this because practically this library does not work on Android 12 and 13. buildToolsVersion = "33.0.0" compileSdkVersion = 33 targetSdkVersion = 33 this is current sdk version used but previous used the 31 of sdk it works on it now complusary to chanage the sdk version so i having the issue in android 13 permission comes of never ask again const grants = await PermissionsAndroid.requestMultiple([ PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, ]); for write external and read extrernal storage came of log never_ask_again how to resolve t

MorganTrudeau commented 1 year ago

I'm doing this

export const atLeastAndroid13 = (): boolean => {
  return Platform.OS === 'android' && Platform.Version >= 33;
};

 const permissions = atLeastAndroid13()
          ? [PERMISSIONS.ANDROID.RECORD_AUDIO]
          : [
              PERMISSIONS.ANDROID.RECORD_AUDIO,
              PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
              PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
            ];

 const res = await checkMultiple(permissions);
efstathiosntonas commented 1 year ago

You need to check for PERMISSIONS.ANDROID.READ_MEDIA_AUDIO on Android >= 13 so you should [PERMISSIONS.ANDROID.RECORD_AUDIO, PERMISSIONS.ANDROID.READ_MEDIA_AUDIO]

abduldeveloper commented 1 year ago

[PERMISSIONS.ANDROID.RECORD_AUDIO]

I did like this its start recording in the android 13 but i did not get path of recorded file could you tell way to get path and need to play of the recorded file

pavelustenko commented 12 months ago

Same issue for me! Have you found any solution?

vitika1 commented 11 months ago

Hey, did anyone find any solution to this?

pavelustenko commented 11 months ago

Hey, did anyone find any solution to this?

@vitika1 Yes. Upgrade to 3.6.0

vitika1 commented 11 months ago

@pavelustenko Thanks for the reply. I am using the latest version only and the example still suggests requesting for WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE. Am I missing something?

pavelustenko commented 11 months ago

@pavelustenko Thanks for the reply. I am using the latest version only and the example still suggests requesting for WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE. Am I missing something?

@vitika1 I actually don't remember clearly what exactly made it work... I've just looked in my android-manifest. Try modify like this:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
pavelustenko commented 11 months ago

@vitika1 Oh, I have found 1 more change:

android:requestLegacyExternalStorage="true"

in application tag.

That's worked for me.

vitika1 commented 11 months ago

@pavelustenko I tried the things which you suggested but unfortunately it didn't work, getting the same error - <filename>: open failed: EROFS (Read-only file system). Really appreciate your help though :)

Mohamedghaly140 commented 11 months ago

it should be updated and be compatible with old and new Android API levels for example version less than 33 will require READ_EXTERNAL_STORAGE & WRITE_EXTERNAL_STORAGE and above or equal 33 may require READ_MEDIA_VIDEO

Sravansuhas commented 11 months ago
 I have added this in the AndroidManifest.xml
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

for Android 13 and above request these permission. 
const grants = await PermissionsAndroid.requestMultiple([
                    PermissionsAndroid.PERMISSIONS.READ_MEDIA_VIDEO,
                    PermissionsAndroid.PERMISSIONS.READ_MEDIA_AUDIO,
                    PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
                ]);

Check the official Android Developers Docs. READ_EXTERNAL_STORAGE & WRITE_EXTERNAL_STORAGE has been changed from Android 13

Fabian15-03 commented 11 months ago

Si , cambiaron en Android 13. ahora estoy intentando hacer que el audio se guarde de forma local en una variable pero la transformación en tiempo real a base64 no es posible por limitaciones. Ahora lo tengo grabando el audio pero la ruta es desconocida. Pensé que era solo tema de Permisos :traffic_light: Alguien podría brindar su StopRecorder() con su addRecordBackListener((e)) para ver la solución?

Sravansuhas commented 11 months ago

Si , cambiaron en Android 13. ahora estoy intentando hacer que el audio se guarde de forma local en una variable pero la transformación en tiempo real a base64 no es posible por limitaciones. Ahora lo tengo grabando el audio pero la ruta es desconocida. Pensé que era solo tema de Permisos 🚥 Alguien podría brindar su StopRecorder() con su addRecordBackListener((e)) para ver la solución?

Use ReactNativeBlobUtil lib to convert. Real time is not possible

const convertBase64 = async (path) => {
    console.log(`Base64 file://${path}`);
    const audioBase64 = await ReactNativeBlobUtil.fs.readFile(`file://${path}`, 'base64')
    //console.log(`Base64`, audioBase64); 
    uploadFileWithProgress(audioBase64);
}
Fabian15-03 commented 11 months ago

Debemos esperar una solución a nivel de biblioteca? O de Permisos para poder acceder a almacenamiento en android 13?

Sravansuhas commented 11 months ago

Debemos esperar una solución a nivel de biblioteca? O de Permisos para poder acceder a almacenamiento en android 13?

No espere a la biblioteca, puede implementarla directamente agregando algunas líneas de código mencionadas anteriormente.

VasylenckoSlava commented 11 months ago

This is my solution that works for all platform. package.json "react-native-audio-recorder-player": "3.6.1"

AndroidManifest.xml

 <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
const onStartRecord = useCallback(async (): Promise<void> => {
    const atLeastAndroid13 = Platform.OS === 'android' && Platform.Version >= 33;

    if (IS_ANDROID) {
      try {
        const grants = await PermissionsAndroid.requestMultiple(
          atLeastAndroid13
            ? [PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, PermissionsAndroid.PERMISSIONS.READ_MEDIA_AUDIO]
            : [
                PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
                PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
                PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
              ],
        );

        console.warn('write external storage', grants);

        if (
          atLeastAndroid13
            ? grants['android.permission.RECORD_AUDIO'] === PermissionsAndroid.RESULTS.GRANTED
            : grants['android.permission.WRITE_EXTERNAL_STORAGE'] === PermissionsAndroid.RESULTS.GRANTED &&
              grants['android.permission.READ_EXTERNAL_STORAGE'] === PermissionsAndroid.RESULTS.GRANTED &&
              grants['android.permission.RECORD_AUDIO'] === PermissionsAndroid.RESULTS.GRANTED
        ) {
          console.warn('permissions granted');
        } else {
          console.warn('All required permissions not granted');

          return;
        }
      } catch (err) {
        console.warn(err);
        return;
      }
    }
abdi4 commented 10 months ago

Upgrading to the latest version (v3.6.2) does it for me

vivek0046 commented 7 months ago

WRITE_EXTERNAL_STORAGE this permission has been made sensitive by google play. We are not able to downgrade compile version to solve this . we are recommended to use storage access framework or media api( doesnt have any good lib i can use)

WRITE_EXTERNAL_STORAGE is not required by our core functionality so its difficult to submit a case and get approved

has anybody found any work arounds to this?

karo-dc commented 6 months ago

Anyone found solution?

3azam0 commented 6 months ago

refactoring permission request worked for me

private onStartRecord = async (): Promise => { if (Platform.OS === 'android') { try { const grants = await PermissionsAndroid.requestMultiple([ // PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, // PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, ]);

    console.log('write external stroage', grants);

    if (
      // grants['android.permission.WRITE_EXTERNAL_STORAGE'] ===
      //   PermissionsAndroid.RESULTS.GRANTED &&
      // grants['android.permission.READ_EXTERNAL_STORAGE'] ===
      //   PermissionsAndroid.RESULTS.GRANTED &&
      grants['android.permission.RECORD_AUDIO'] ===
      PermissionsAndroid.RESULTS.GRANTED
    ) {
      console.log('permissions granted');
    } else {
      console.log('All required permissions not granted');

      return;
    }
  } catch (err) {
    console.warn(err);

    return;
  }
Iamfavur commented 4 months ago

refactoring permission request worked for me

private onStartRecord = async (): Promise => { if (Platform.OS === 'android') { try { const grants = await PermissionsAndroid.requestMultiple([ // PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, // PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, ]);

    console.log('write external stroage', grants);

    if (
      // grants['android.permission.WRITE_EXTERNAL_STORAGE'] ===
      //   PermissionsAndroid.RESULTS.GRANTED &&
      // grants['android.permission.READ_EXTERNAL_STORAGE'] ===
      //   PermissionsAndroid.RESULTS.GRANTED &&
      grants['android.permission.RECORD_AUDIO'] ===
      PermissionsAndroid.RESULTS.GRANTED
    ) {
      console.log('permissions granted');
    } else {
      console.log('All required permissions not granted');

      return;
    }
  } catch (err) {
    console.warn(err);

    return;
  }

Hello, please are you able to record audio, play audio and get the storage location as you have commented out the two requests?