После некоторых исследований и отладки я нашел причину проблемы и решение для нее.
Почему это происходит?
Firebase использует метод atob
для декодирования строки base64, отправленной методом putstring
.
Однако, поскольку JavaScriptCore не имеет поддержки по умолчанию atob
и btoa
, строка base64 не может быть преобразована, поэтому вызывается это исключение.
Когда мы запускаем приложение в режиме отладки javascript удаленно, весь код javascript запускается в среде chrome, где поддерживаются atob
и btoa
. Вот почему код работает, когда включена отладка, и не работает, когда она выключена.
Как решить?
Чтобы обработать atob
и btoa
в React Native, мы должны либо написать наш собственный метод кодирования / декодирования, либо установить lib для его обработки за нас.
В моем случае я предпочел установить base-64
lib
Но вот пример сценария кодирования / декодирования:
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const Base64 = {
btoa: (input:string = '') => {
let str = input;
let output = '';
for (let block = 0, charCode, i = 0, map = chars;
str.charAt(i | 0) || (map = '=', i % 1);
output += map.charAt(63 & block >> 8 - i % 1 * 8)) {
charCode = str.charCodeAt(i += 3/4);
if (charCode > 0xFF) {
throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
}
block = block << 8 | charCode;
}
return output;
},
atob: (input:string = '') => {
let str = input.replace(/=+$/, '');
let output = '';
if (str.length % 4 == 1) {
throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
}
for (let bc = 0, bs = 0, buffer, i = 0;
buffer = str.charAt(i++);
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
) {
buffer = chars.indexOf(buffer);
}
return output;
}
};
export default Base64;
Использование:
import Base64 from '[path to your script]';
const stringToEncode = 'xxxx';
Base64.btoa(scriptToEncode);
const stringToDecode = 'xxxx';
Base64.atob(stringToDecode);
После выбора использования пользовательского сценария или библиотеки lib теперь необходимо добавить следующий код в файл index.js
:
import { decode, encode } from 'base-64';
if (!global.btoa) {
global.btoa = encode;
}
if (!global.atob) {
global.atob = decode;
}
AppRegistry.registerComponent(appName, () => App);
Это объявит atob
и btoa
во всем мире. Поэтому всякий раз, когда в приложении вызываются эти функции, React Native будет использовать глобальную область действия для его обработки, а затем запускать методы encode
и decode
из base-64
lib.
Так что это решение проблемы Base64.
Однако после того, как это было решено, я обнаружил еще одну проблему Firebase Storage: Max retry time for operation exceed. Please try again
при попытке загрузить изображения большего размера. Кажется, что firebase
имеет некоторые ограничения на поддержку React Native закачек , как эта проблема предполагает.
Я полагаю, что react-native-firebase
может и не бороться с этим, поскольку он уже подготовлен для собственного запуска, вместо использования веб-среды, как firebase
. Я еще не проверял это, чтобы подтвердить, но, похоже, это будет лучшим подходом к решению проблемы.
Надеюсь, это может быть полезно для кого-то еще.