I'm facing an issue while trying to use the IONIC Cordova File Transfer plugin to upload a file while the laravel Server is running in HTTPS.
I'm able to login to the application and access all APIs from the server with get and post, but when I try to use fileTransfer for uploading data I'm getting the below message.
body: null
code: 3
exception: "java.security.cert.CertPathValidatorException: Trust anchor for certification path not found."
http_status: null
source: "content://com.android.providers.media.documents/document/image%3A16679"
target: "https://reddyflix.com/api/profile/photo/update"
I have dowloaded the (.cer) certificate file into the www directory of the project and setSSLCertMode = pinned. But I am still facing this issue.
let options: FileUploadOptions = {
httpMethod: "post",
chunkedMode: false,
fileKey: 'file',
fileName: 'name.png',
headers: headers
};
let trustAllHosts = true;
fileTransfer.upload(
uri,encodeURI('https://domain/api/profile/photo/update'), options,trustAllHosts)
.then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
Related
I'm having some difficulties trying upload video file to server using Cordova Camera Plugin and cordova-plugin-advanced-http. The code works like a charm when uploading an image from gallery, but no matter what I do, I always receive EACCES (Permission denied) when uploading a video from gallery:
file url -> file:///storage/emulated/0/DCIM/Camera/VID_20200908_114957.mp4
post-post-module-es2015.js:240 {status: -1, error: "There was an error with the request: /storage/emulated/0/DCIM/Camera/VID_20200908_114957.mp4: open failed: EACCES (Permission denied)"
Looking only at the error message, we can conclude it's a permission issue, so I tried use cordova-plugin-android-permissions and request READ_EXTERNAL_STORAGE permission. No success, the app has the permission but the error remains the same.
This is part of the code used to upload
private chooseContentUsingCameraPlugin(SOURCE: number) {
const options: CameraOptions = {
destinationType: this.camera.DestinationType.FILE_URI,
mediaType: this.camera.MediaType.ALLMEDIA,
sourceType: SOURCE
};
this.camera.getPicture(options).then((contentUrl: string) => {
if (contentUrl.indexOf('://') === -1)
contentUrl = 'file://' + contentUrl;
const queryIndex = contentUrl.lastIndexOf('?');
if (queryIndex !== -1)
contentUrl = contentUrl.substring(0, queryIndex);
console.log('file url -> ', contentUrl);
this.startUpload(contentUrl);
}, (err) => this.onUploadError(err));
}
private startUpload(fileUrl){
...
this.nativeHttp.uploadFile(req.url, null, headers, fileUrl, fileName).then(res => {
let data = res.data;
if (res.data && (req.responseType === undefined || req.responseType === 'json'))
data = JSON.parse(res.data);
console.log(data)
}).catch(error => {
console.log(error)
});
}
can someone explain what could be causing this issue?
It's possible that the file you're trying to upload is not in the scope of your permission. This is what the documentation says:
This is a soft restricted permission which cannot be held by an app it its full form until the installer on record whitelists the permission. Specifically, if the permission is whitelisted the holder app can access external storage and the visual and aural media collections while if the permission is not whitelisted the holder app can only access to the visual and aural medial collections. Also the permission is immutably restricted meaning that the whitelist state can be specified only at install time and cannot change until the app is installed. For more details see PackageInstaller.SessionParams.setWhitelistedRestrictedPermissions(Set).
Server side is Django/python.
Client environment is cordova/android.
This request fails :
$.ajax({
url: myAddress,
type: 'POST',
data: mydata,
crossDomain: true,
processData: false,
contentType: false,
async: false,
success: function () { mycode},
error: function (xhr) { mycode} }
});
When myAddress is 192.168.1.11 it works perfectly.
When myAddress is dev.mysite.com i get the error:
NetworkError: Failed to execute 'send' on XMLHttpRequest': Failed to load dev.mysite.com/../..
However, i can connect to the same django web server with chrome on the mobile device.
config.xml contains : access origin="*"
Do you have an idea to solve this problem?
The js code is good.
The CSP code is good.
My problem came from my misunderstanding of http redirection at the DNS level.
Thank you for you attention
I am developing an app using Phonegap Build for a customer that has chosen not to use the Google Play Store. Instead, they are opting to have me privately host the APK files for the app.
I am trying to develop a way to dynamically check my server every time the app is launched to check to see if there is an update and if there is, to download and install that update.
I do an ajax request to my server to check for the latest file, I then return the latest version number and URL of the file on AWS to my frontend. If the file version is greater than the current app version, I want to update.
Here's the code I have right now using the FileTransfer and Web Intent plugins for Phonegap Build:
$.ajax
type: 'GET'
dataType: 'json'
url: "#{baseUrl}/v2/update"
data:
app_token: 'fubar'
success: (data) =>
window.downloadApkAndroid(data)
window.downloadApkAndroid = (data) ->
fileURL = "cdvfile://localhost/persistent/#{data.filename}"
fileTransfer = new FileTransfer
uri = encodeURI(data.download_url)
fileTransfer.download uri, fileURL, ((entry) ->
alert 'download complete: ' + entry.fullPath
promptForUpdateAndroid entry
return
), ((error) ->
console.log 'download error source ' + error.source
console.log 'download error target ' + error.target
console.log 'upload error code' + error.code
alert "#{error.code} + #{error.source} + #{error.target}"
return
), false, {}
return
window.promptForUpdateAndroid = (entry) ->
alert entry
window.plugins.webintent.startActivity {
action: window.plugins.webintent.ACTION_VIEW
url: entry.toURL()
type: 'application/vnd.android.package-archive'
}, (->
), ->
alert 'Failed to open URL via Android Intent.'
console.log 'Failed to open URL via Android Intent. URL: ' + entry.fullPath
return
return
Nothing happens when I launch the app, though. I am returning a newer version from the first Ajax request and the success method is being called. But nothing seems to happen after that. Can anyone tell me any better methods of doing this or what I'm doing wrong here?
Have you considered using the Cordova Hot Code Push plugin, which would allow you to update your application's www folder (the app views, JS, CSS, any images etc) without having to do a Google Play update. This method would allow you to ship a version of your application in the apk, and periodically get updates from a server without having to build boilerplate file fetching code yourself.
For some reason my Cordova built app cannot send POST requests as a mobile application. If I run it from a browser (in my PC or mobile device) it works fine, but when I run it as mobile app request fails giving 403 forbidden error. Maybe someone has encountered similar problem before and knows what to do?
P.S. GET requests work fine.
config.xml:
<access origin="mytestserver.eu/test"/>
.js:
$.ajax({
type: 'POST',
url: "http://mytestserver.eu/test",
data: '{ "test": "Test"}',
dataType:'json',
headers: {
'Content-Type': 'application/json'
},
crossDomain: true,
success: function(data, textStatus, request){
alert ($.toJSON(data));
},
error: function (request, textStatus, errorThrown) {
alert ($.toJSON(errorThrown));
}
});
This issue was resolved when I disabled ModSecurity on my server.
For me, I was able to do that via the cPanel access to my host:
cPanel > Security > ModSecurity
I am building an Android app that is hosted on a server outside Google Play. I need the app to check for new version and prompt user to update when the app starts.
I built a mechanism to check for new version (the app checks for a file on server and compares version) which is working well. Then I prompt user to update, but if user chooses to proceed with the update, I'm not able to trigger the download and installation of the apk.
I tried simply opening the apk url:
window.open(apkURL);
where the apkURL is the full http link to the .apk file hosted on server.
But it doesn't seem to do anything.
I've been researching but I don't find an answer on how to do this. I found some suggestions using native code, like this post Install Application programmatically on Android but I don't know how to do that from within my Phonegap app.
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("file:///path/to/your.apk"))
.setType("application/vnd.android.package-archive");
startActivity(promptInstall);
Is this the right way to trigger the update? How can something like this be done from within a Phonegap app?
Thanks!
I finally managed to implement this, using the File api and the WebIntent plugin. I will post the solution here in case it helps anyone.
The code downloads the apk from a remote server to the download folder in the sdcard and then triggers the install.
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile('download/filename.apk', {
create: true,
exclusive: false
}, function(fileEntry) {
var localPath = fileEntry.fullPath,
fileTransfer = new FileTransfer();
fileTransfer.download(apkURL, localPath, function(entry) {
window.plugins.webintent.startActivity({
action: window.plugins.webintent.ACTION_VIEW,
url: 'file://' + entry.fullPath,
type: 'application/vnd.android.package-archive'
},
function(){},
function(e){
alert('Error launching app update');
}
);
}, function (error) {
alert("Error downloading APK: " + error.code);
});
}, function(evt){
alert("Error downloading apk: " + evt.target.error.code);
});
}, function(evt){
alert("Error preparing to download apk: " + evt.target.error.code);
});
For you guys that use Cordova 3+, a similar solution like that of Vero is possible:
So we're first going to download the .apk file. We need the file-transfer plugin for this.
You can install it with following command:
phonegap local plugin add org.apache.cordova.file-transfer
Secondly, we need another plugin to start a webintent. This webintent prompts the user if there is an update. You can install it with the following command:
phonegap local plugin add https://github.com/Initsogar/cordova-webintent.git
Then, you can use this 2 functions in your code to download the .apk and to prompt the user if
there is an update of the application:
/*
* Uses the filetransfer plugin
*/
function downloadApkAndroid(data) {
var fileURL = "cdvfile://localhost/persistent/CegekaMon.apk";
var fileTransfer = new FileTransfer();
var uri = encodeURI(data.android);
fileTransfer.download(
uri,
fileURL,
function (entry) {
console.log("download complete: " + entry.fullPath);
promptForUpdateAndroid(entry);
},
function (error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
},
false,
{
}
);
}
/*
* Uses the borismus webintent plugin
*/
function promptForUpdateAndroid(entry) {
window.plugins.webintent.startActivity({
action: window.plugins.webintent.ACTION_VIEW,
url: entry.toURL(),
type: 'application/vnd.android.package-archive'
},
function () {
},
function () {
alert('Failed to open URL via Android Intent.');
console.log("Failed to open URL via Android Intent. URL: " + entry.fullPath);
}
);
}
Sadly you cannot access that kind of native feature within a Phonegap web container without using a plugin, all you can do is link the user to the apk (by opening the native browser for instance) and let him install it.
thank you Vero for answer ... it is help me so much...
there is a problem with your code in cordova file plugin last version.
replace entry.fullPath with entry.toURL() if you use file plugin version 1.0.0 or newer.
if you use entry.fullPath , it throw error 'there is a problem parsing package'.
from file-transfer plugin on github
These paths were previously exposed in the fullPath property of FileEntry and DirectoryEntry objects returned by the File plugin. New versions of the File plugin, however, no longer expose these paths to JavaScript.
If you are upgrading to a new (1.0.0 or newer) version of File, and you have previously been using entry.fullPath as arguments to download() or upload(), then you will need to change your code to use filesystem URLs instead.
FileEntry.toURL() and DirectoryEntry.toURL() return a filesystem URL of the form
cdvfile://localhost/persistent/path/to/file
which can be used in place of the absolute file path in both download() and upload() methods.
Working example in 2018
Based on previous comments I implement this solution
It require:
File plugin
File transfer plugin
Web intent plugin
constructor(public navCtrl: NavController, private transfer: FileTransfer, private file: File, private webIntent: WebIntent) {
const fileTransfer: FileTransferObject = this.transfer.create();
const url = 'urlApkFile';//Modified this
fileTransfer.download(url, this.file.externalDataDirectory + 'file.apk').then((entry) =>
{
webIntent.startActivity({
action: (window).plugins.intentShim.ACTION_INSTALL_PACKAGE,
url: entry.toURL(),
type: 'application/vnd.android.package-archive'
}).then(function () {
//OK
}, function (e) {
alert('Error launching app update' + JSON.stringify(e));
});
}, (error) => {
alert("downdload finish" + JSON.stringify(error));
});
}