Ionic Native Camera — 0 Byte Fotoğraf Kaydetme Sorunu (Çözüm)

Merhaba arkadaşlar, geçenlerde Ionic 3 ile yazdığım bir uygulamada Ionic Native Camera (cordova-camera) modülünü kullanarak bir klasöre fotoğraf kaydetmem gerekti. Hiçbir yer belirtmezseniz cordova otomatik olarak Android/data/cache klasörünün altına kaydediyor, fakat Clean Master gibi cache temizleyen programlar bu fotoğrafları silebiliyor. O yüzden dataDirectory dediğimiz uygulamaya ait bölüme kaydetmek daha mantıklı oluyor.

Fotoğrafı base64 encoded olarak çekip bloba çevirip camera.writeFile metoduna gönderiyordum. Olumlu senaryoda her şey güzel çalıştı, fakat bazı Android cihazlarda bir şekilde fotoğraf çekerken timeouta düşüyor, ne hata veriyor ne başarılı oluyor. Fotoğrafı kaydediyor fakat 0 byte boyutlu bir fotoğraf oluşturuyor. Haliyle kaydetmesinin bir esprisi olmuyor.

Biraz araştırma yaptığımda anladım ki, polyfill ve cordovanın index.html’deki sırası önemliymiş. Polyfill dosyasını cordova.js dosyasının üzerine alınca sorun yaşanan Android cihazlarda da sorun çözüldü. İsterseniz kodlarla açıklayayım;

Fotoğraf Kaydetme

// Fotoğraf çekme ve kaydetmenin başlatıldığı fonksiyon
// Önyüzden bu fonksiyonu çağırdığınız zaman kamera açılır ve fotoğraf kaydedilir.
public getPicture() {
// Kamera seçenekleri burada belirtiliyor
const options: CameraOptions = {
    quality: 50,
    destinationType: this.camera.DestinationType.DATA_URL,
    encodingType: this.camera.EncodingType.JPEG,
    mediaType: this.camera.MediaType.PICTURE,
    sourceType: this.camera.PictureSourceType.CAMERA,
    cameraDirection: 0,
}
this.camera.getPicture(options).then(imageData => {
    let name = "Fotograf.jpg";
    let path = this.file.dataDirectory;
    let options: IWriteOptions = { replace: true };
    // Burada base64u Bloba çeviriyoruz.
    let blob = this.b64toBlob(imageData, 'image/jpeg');
    this.file.writeFile(path, name, blob, options).then(res => {
        this.presentToaster("Fotoğraf kaydedildi.");
    }).catch(err => {
        this.presentToaster("Fotoğraf eklenirken hata oluştu.");
    });
  });
}

// Bloba çevirme fonksiyonu
b64toBlob(b64Data, contentType) {
  contentType = contentType || '';
  let sliceSize = 512;
  let byteCharacters = atob(b64Data);
  let byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    let slice = byteCharacters.slice(offset, offset + sliceSize);

    let byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    let byteArray = new Uint8Array(byteNumbers);

    byteArrays.push(byteArray);
  }

  let blob = new Blob(byteArrays, { type: contentType });
  return blob;
}

Buraya kadar her şey çok güzel çalışıyor. Fotoğrafı çekiyor ve base64 olarak gelen veriyi bloba çevirip yazıyor ama sadece bazı cihazlarda. Stabilitenin sağlanması açısından aşağıdaki sıralamayı da değiştirmek gerekiyor.

index.html Polyfills ve Cordova Sıralaması

Pollyfills.js script etiketi cordova.jsnin üzerine alınmalıdır, şu şekilde;

<script src="build/polyfills.js"></script>
<script src="cordova.js"></script>

Böyle bir deneyim yaşadım, umarım bu yazı bir gün birinin işine yarar ve faydalı bir iş yapmış olurum. Sağlıcakla kalın :)