Reputation: 743
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
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