JoeyD
JoeyD

Reputation: 743

Ionic-Native PhotoLibrary Crashes on SaveImage when running on Android

I am attempting to do something very simple yet it is causing me much pain.

I have an Ionic v5 Angular 12 application and have installed the Ionic-Native/PhotoLibrary plugin

https://ionicframework.com/docs/v5/native/photo-library

I am using the Ionic-Native version as recommended by the plugin itself

https://github.com/terikon/cordova-plugin-photo-library

Here is my code

import { PhotoLibrary } from '@ionic-native/photo-library/ngx';


constructor(private photoLibrary: PhotoLibrary) { }

const blob = new Blob(binaryData, { type: dataType });
this.file.writeFile(this.file.dataDirectory, attachment.name, blob, { replace: true }).then(() => {
     console.log('file should be saved');
     let libraryItem = this.photoLibrary.saveImage(this.file.dataDirectory + attachment.name, "RaceApp");   
     console.log('photo should be saved to album');    
});

When running in android studio I see the following in the console

I/Capacitor/Console: File: https://localhost/main.js - Line 3687 - Msg: file should be saved
D/MediaScannerConnection: Scanned /storage/emulated/0/Pictures/RaceApp/2022-2-9-6.jpeg to content://media/external_primary/images/media/9512

E/AndroidRuntime: FATAL EXCEPTION: android.bg
    Process: com.pyrix.racechat, PID: 10114
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.json.JSONObject.toString()' on a null object reference
        at org.apache.cordova.PluginResult.<init>(PluginResult.java:55)
        at org.apache.cordova.CallbackContext.success(CallbackContext.java:70)
        at com.terikon.cordova.photolibrary.PhotoLibrary$5$1.run(PhotoLibrary.java:212)
        at com.terikon.cordova.photolibrary.PhotoLibraryService$2.run(PhotoLibraryService.java:214)
        at com.terikon.cordova.photolibrary.PhotoLibraryService$5.onScanCompleted(PhotoLibraryService.java:579)
        at android.media.MediaScannerConnection.runCallBack(MediaScannerConnection.java:211)
        at android.media.MediaScannerConnection.lambda$scanFile$1(MediaScannerConnection.java:188)
        at android.media.MediaScannerConnection$$ExternalSyntheticLambda0.run(Unknown Source:6)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.os.HandlerThread.run(HandlerThread.java:67)

I do see that the RaceApp Album has been created and the photo is saved to that album. What I do not understand is why the application is crashing and that error is being shown.

Upvotes: 2

Views: 554

Answers (1)

Suryakant kumar
Suryakant kumar

Reputation: 190

Here is an alternative way to store base64 image to file/photo library. In my case I have tested it on Ionic 5, cordova 11, and angular 12, Its working nicely.

Plugins used

ionic cordova plugin add cordova-plugin-photo-library --force

npm install @awesome-cordova-plugins/photo-library@6

 saveFile(base64Data) {
    let UUID = 'IMAGE_NAME_' + (new Date().getTime()).toString(16);
    let realData = base64Data.split(",")[1];
    let blob = this.b64toBlob(realData, 'image/jpeg');
    this.file.checkDir(this.file.externalRootDirectory, 'DCIM').then(result => {
      console.log('Directory exists: ' + JSON.stringify(result));
      this.file.writeFile(this.file.externalRootDirectory + 'DCIM/', UUID + '.jpg', blob).then(res => {
        console.log('File created success: ' + JSON.stringify(res));
      }).catch(err => {
        console.log('File created failed: ' + JSON.stringify(err));
      });
    }).catch(err => {
      console.log('Directory not exists: ' + JSON.stringify(err));
      this.file.createDir(this.file.externalRootDirectory, 'DCIM', false).then(result => {
        console.log('Directory created Success: ' + JSON.stringify(result));
        this.file.writeFile(this.file.externalRootDirectory + 'DCIM/', UUID + '.jpg', blob).then(res => {
          console.log('File created success: ' + JSON.stringify(res));
        }).catch(err => {
          console.log('File created failed: ' + JSON.stringify(err));
        });
      }).catch(err => {
        console.log('Directory created Failed: ' + JSON.stringify(err));
      });
    });
  }
  b64toBlob(b64Data, contentType) {
    contentType = contentType || '';
    var sliceSize = 512;
    var byteCharacters = atob(b64Data);
    var byteArrays = [];

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

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

      var byteArray = new Uint8Array(byteNumbers);

      byteArrays.push(byteArray);
    }

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

}

Upvotes: 3

Related Questions